Reputation: 107
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?
A.set()
, A::data
is set to A::_default
A.set(a)
, A::data
is set to a
Upvotes: 2
Views: 450
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
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
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