Why are these arguments allowed by default?

I found this question and am completely puzzled.

The response says b is false: "Non-static members cannot be used as default arguments." It makes sense.

What I don't understand is why the other two are fine. In fact, I'm trying to understand what semantics is, if the default is not a constant expression ...

What's going on here? The default parameters are clearly evaluated at compile time. Does the compiler just 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 << fa() << std::endl; std::cout << fb() << std::endl; std::cout << fc() << std::endl; return 0; } 
+5
c ++ default-arguments
Nov 19 '14 at 13:37
source share
3 answers

Actually, the default arguments are evaluated when the function is called, so this is normal. From the draft C ++ draft, section 8.3.6 The default arguments that say (emphasis mine in the future):

The default arguments are evaluated each time the function is called . The evaluation order of the function arguments is not specified. Therefore, function parameters should not be used as the default argument, even if they are not evaluated. Function parameters are declared before the default argument in scope and can hide the namespace and member names of the class.

The following example from the same section gives us justification for why we can use static elements, but not non-static:

[Example: the declaration of X :: mem1 () in the following example: is poorly formed because an X :: a object is not provided for a non-static element 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; }; 

Declaring X :: mem2 () makes sense, however, since no object is required to access the static element X :: b. Classes, objects, and members are described in section 9. -end example]

+8
Nov 19 '14 at 13:42 on
source share

The default arguments are not evaluated at compile time. They are evaluated every time a function call is required. They can be any expression that acts in the context of a function declaration and is of a suitable type, except that it cannot use any other parameters (including this , in the case of a member function).

This limitation is due to the fact that the evaluation order is not specified, therefore it is not possible to ensure the availability of the parameter value if it is necessary to evaluate another argument.

+7
Nov 19 '14 at 13:42 on
source share

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 the trick to use m_x:

 int b(int x = -1) { return x == -1 ? m_x + 1 : x + 1; } 

(Of course, -1 in this case should be illegal.)

0
Nov 19 '14 at
source share



All Articles