Nonstatic member as a default argument of a nonstatic member function

后端 未结 9 1020
攒了一身酷
攒了一身酷 2020-11-28 05:56
struct X
{
   X():mem(42){}
   void f(int param = mem) //ERROR
   {
      //do something
   }
private: 
   int mem;
};

Can anyone give me just one

相关标签:
9条回答
  • 2020-11-28 06:20

    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?
    0 讨论(0)
  • 2020-11-28 06:20

    Default arguments are evaluated in two distinct steps, in different contexts.
    First, the name lookup for the default argument is performed in the context of the declaration.
    Secondly, the evaluation of the default argument is performed in the context of the actual function call.

    To keep the implementation from becoming overly complicated, some restrictions are applied to the expressions that can be used as default arguments.

    • Variables with non-static lifetime can't be used, because they might not exist at the time of the call.
    • Non-static member variables can't be used, because they need an (implicit) this-> qualification, which can typically not be evaluated at the call site.
    0 讨论(0)
  • 2020-11-28 06:21

    As DeadMG has mentioned above, somethig like

    void func(int i, int f = g(i))

    is illegal for the same reason. i suppose, however, that it is not simply a silly restriction. To allow such a construction, we need to restrict evaluation order for function parameters (as we need to calculate this before this->mem), but the c++ standard explicitly declines any assumptions on the evaluation order.

    0 讨论(0)
  • 2020-11-28 06:27

    The accepted answer in the duplicate question is why, but the standard also explicitly states why this is so:

    8.3.6/9:

    " Example: the declaration of X::mem1() in the following example is ill-formed because no object is supplied for the nonstatic member X::a used as an initializer.

    int b;
    class X
      int a;
      int mem1(int i = a);    // error: nonstatic 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. "

    ... and since there exists no syntax to supply the object necessary to resolve the value of X::a at that point, it's effectively impossible to use non-static member variables as initializers for default arguments.

    0 讨论(0)
  • 2020-11-28 06:30

    ISO C++ section 8.3.6/9

    a nonstatic member shall not be used in a default argument expression, even if it is not evaluated, unless it appears as the id-expression of a class member access expression (5.2.5) or unless it is used to form a pointer to member (5.3.1).

    Also check out the example given in that section.

    0 讨论(0)
  • 2020-11-28 06:37

    Compiler has to know addresses to maintain default values at compile time. Addresses of non-static member variables are unknown at compile time.

    0 讨论(0)
提交回复
热议问题