LI.LE
LI.LE

Reputation: 107

member variable as default argument?

I got "a nonstatic member reference must be relative to a specific object" with the following code,

class A{
    int data;
    int _default = 0;
public:
    A(int data, int _default) : data(data), _default(_default) {}
    void set(int data = _default){ this->data = data; }
};

int main(){
    A a1(1, 1); a1.set(10); a1.set();
    A a2(2, 2); a2.set(20);
}

What I want to do?

Upvotes: 2

Views: 450

Answers (3)

Peter
Peter

Reputation: 36637

From the 2017 C++ standard, section 11.3.6, para 9

A non-static member shall not appear in a default argument unless it appears as the id-expression of a class member access expression (8.2.5) or unless it is used to form a pointer to member (8.3.1).

All other C++ standards (before and since) have a similar statement, although the wording and section numbers vary. Neither of the "unless" points in the above are applicable in this case.

It is notionally possible (since C++17) to use std::optional (from header <optional>) to avoid the overload, as follows.

#include <optional>

class A
{
     int data;
     int _default = 0;
   public:
     // other members omitted
   
     void set(std::optional<int> data = std::optional<int>())
     {
         this->data = data.has_value() ? data.value() : _default;
     };
 };

or (as suggested by Jarod42 in comments)

     void set(std::optional<int> data = std::nullopt)
     {
         this->data = data.value_or(_default);
     };

I use the word "notionally" in the above because, personally, I would simply use two overloads. It is (arguably) easier for a mere mortal to understand and works with all C++ standards (not just since C++17)

 void set(int data){ this->data = data; }
 void set(){ set(this->_default); }       

Upvotes: 5

foragerDev
foragerDev

Reputation: 1409

what you can do is you can provide an overload.

void set(){ this->data = this->_default; }
void set(int data){ this->data = data; }

This will accomplish the job you want to do.

Upvotes: 3

songyuanyao
songyuanyao

Reputation: 173044

Non-static data members can't be used as default arguments, which are supposed to be provided from the caller side context.

Non-static class members are not allowed in default arguments (even if they are not evaluated),

You could provide another overload.

class A{
    int data;
    int _default = 0;
public:
    A(int data, int _default) : data(data), _default(_default) {}
    void set(int data){ this->data = data; }
    void set(){ set(this->_default); }
};

Upvotes: 6

Related Questions