Reputation: 96258
I've found this question, and I'm completely baffled.
The answer says b
is invalid, "Non-static members can not be used as default arguments.". That makes perfect sense.
What I don't understand is why the other two are okay. In fact, I'm struggling to understand what the semantics are if the default is not a constant expression...
What's going on here? Default parameters are clearly evaluated at compile time. Does the compiler simply pick the current value?
#include <iostream>
int g_x = 44;
struct Foo
{
int m_x;
static int s_x;
Foo(int x) : m_x(x) {}
int a(int x = g_x) { return x + 1; }
int b(int x = m_x) { return x + 1; }
int c(int x = s_x) { return x + 1; }
};
int Foo::s_x = 22;
int main(int argc, char** argv)
{
Foo f(6);
std::cout << f.a() << std::endl;
std::cout << f.b() << std::endl;
std::cout << f.c() << std::endl;
return 0;
}
Upvotes: 5
Views: 323
Reputation: 158459
Actually, default arguments are evaluated when the function is called, which is why this is okay. From the draft C++ standard section 8.3.6
Default arguments which says (emphasis mine going forward):
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 a default argument, even if they are not evaluated. Parameters of a function declared before a default argument are in scope and can hide namespace and class member names.
The following example from the same section gives us a rationale for why we can use static members but not non-static ones:
[ Example: the declaration of X::mem1() in the following example is ill-formed because no object is supplied for the non-static member X::a used as an initializer.
int b; class X { int a; int mem1(int i = a); // error: non-static member a // used as default argument int mem2(int i = b); // OK; use X::b static int b; };
The declaration of X::mem2() is meaningful, however, since no object is needed to access the static member X::b. Classes, objects, and members are described in Clause 9. —end example ]
Upvotes: 8
Reputation: 567
I think this is understandable: g_x and s_x are available at compile time but this (and therefore this->m_x) is not. You can use a trick to use m_x:
int b(int x = -1) { return x == -1 ? m_x + 1 : x + 1; }
(Of course -1 should be illegal input in this case.)
Upvotes: 0
Reputation: 254431
Default arguments aren't evaluated at compile time. They're evaluated each time a function call requires them. They can be any expression that's valid in the context of the function declaration and has a suitable type, except that it can't use any other parameters (including this
, in the case of a member function).
That restriction is because the evaluation order isn't specified, so there's no way to ensure a parameter value is available if it were needed to evaluate another argument.
Upvotes: 7