Nonstatic member as a default argument of a nonstatic member function
Your code (simplified):
struct X
{
int mem;
void f(int param = mem); //ERROR
};
You want to use a non-static member data as default value for a parameter of a member function. The first question which comes to mind is this : which specific instance of the class the default value mem
belongs to?
X x1 = {100}; //mem = 100
X x2 = {200}; //mem = 200
x1.f(); //param is 100 or 200? or something else?
Your answer might be 100
as f()
is invoked on the object x1
which has mem = 100
. If so, then it requires the implementation to implement f()
as:
void f(X* this, int param = this->mem);
which in turn requires the first argument to be initialized first before initialization of other argument. But the C++ standard doesn't specify any initialization order of the function arguments. Hence that isn't allowed. Its for the same reason that C++ Standard doesn't allow even this:
int f(int a, int b = a); //§8.3.6/9
In fact, §8.3.6/9 explicitly says,
Default arguments are evaluated each
time the function is called. The order
of evaluation of function arguments is
unspecified. Consequently, parameters
of a function shall not be used in
default argument expressions, even if
they are not evaluated.
And rest of the section is an interesting read.
An interesting topic related to "default" arguments (not related to this topic though):
- Default argument in the middle of parameter list?
Default arguments as non-static member variables
Overload Bar
:
int Bar()
{
return x_ + y_;
}
int Bar(int x)
{
return x + y_;
}
int Bar(int x, int y)
{
return x + y;
}
Thanks to @Jarod42 for this improvement:
int Bar(int a, int b)
{
return a + b;
}
int Bar(int a)
{
return Bar(a, y_);
}
int Bar()
{
return Bar(x_, y_);
}
The real-world problem you're trying to solve is more likely to benefit from this refactoring than the original problem of summing two numbers. This behavior is more obviously identical to that you were hoping to achieve through default arguments.
c++ default parameters
You can't do that.
You can however have an overload for test
that takes no parameters.
void test(){
test(_x);
}
C++11: Use non-static member function as default argument in class constructor
class Foo
{
public:
using CallbackType = std::function<void(void)>;
Foo() : Foo([this]{defaultCallback();}) {}
explicit Foo(CallbackType callback) : _callback(callback) {}
void defaultCallback(void) {}
CallbackType _callback;
};
Using a non static value as default argument in a function
One relatively elegant way (in my opinion) would be to use std::optional
to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
Non static members as default parameters in C++
How about :
class MyClass
{
public:
CMyObject A,B;
void MyFunc()
{
MyFunc(A);
}
void MyFunc(CMyObject &Object);
};
?
initializing default parameter with class member function/variable
The default argument is considered to be provided from the caller side context. It just doesn't know the object on which the non-static member function return5
could be called on.
You can make return5
a static
member function, which doesn't require an object to be called on. E.g.
class C {
...
static int return5() { return 5; }
void f(int d = return5()) {
}
...
};
Or make another overload function as
class C {
private:
int n{ 5 };
public:
int return5() { return 5; }
void f(int d) {
}
void f() {
f(return5());
}
void ff(int d) {
}
void ff() {
ff(n);
}
};
Related Topics
How to Have Multiple Parameter Packs in a Variadic Template
How to Cin Values into a Vector
C++ Equivalent to Java's Blockingqueue
Is It Safe to Push_Back an Element from the Same Vector
Is Using Double Faster Than Float
Declare Abstract Signal in Interface Class
Std::Set with User Defined Type, How to Ensure No Duplicates
How to Use Boost Bind with a Member Function
C/C++ Header and Implementation Files: How Do They Work
Checking a Member Exists, Possibly in a Base Class, C++11 Version
Convert String Containing Several Numbers into Integers
Why Should I Use the "Using" Keyword to Access My Base Class Method
"Relocation R_X86_64_32S Against " Linking Error
How to Achieve "Virtual Template Function" in C++
C++ Exception:Throwing Std::String