struct X
{
X():mem(42){}
void f(int param = mem) //ERROR
{
//do something
}
private:
int mem;
};
Can anyone give me just one
Default arguments have to be known at compile-time. When you talk about something like a function invocation, then the function is known at compile-time, even if the return value isn't, so the compiler can generate that code, but when you default to a member variable, the compiler doesn't know where to find that instance at compile-time, meaning that it would effectively have to pass a parameter (this
) to find mem. Notice that you can't do something like void func(int i, int f = g(i));
and the two are effectively the same restriction.
I also think that this restriction is silly. But then, C++ is full of silly restrictions.
For one reason, because f
is public, but mem
is private. As such, code like this:
int main() {
X x;
x.f();
return 0;
}
...would involve outside code retrieving X's private data.
Aside from that, it would (or at least could) also make code generation a bit tricky. Normally, if the compiler is going to use a default argument, it gets the value it's going to pass as part of the function declaration. Generating code to pass that value as a parameter is trivial. When you might be passing a member of an object (possibly nested arbitrarily deeply) and then add in things like the possibility of it being a dependent name in a template, that might (for example) name another object with a conversion to the correct target type, and you have a recipe for making code generation pretty difficult. I don't know for sure, but I suspect somebody thought about things like that, and decided it was better to stay conservative, and possibly open thins up later, if a good reason was found to do so. Given the number of times I've seen problems arise from it, I'd guess it'll stay the way it is for a long time, simply because it rarely causes problems.
As all the other answers just discuss the problem, I thought I would post a solution.
As used in other languages without default arguments (Eg C# pre 4.0)
Simply use overloading to provide the same result:
struct X
{
X():mem(42){}
void f(int param)
{
//do something
}
void f()
{
f(mem);
}
private:
int mem;
};