Search code examples
c++member-functionsdefault-arguments

Is it possible to use member function call as default argument?


Here is my code:

struct S
{
   int f() { return 1; }
   int g(int arg = f()) { return arg; }
};

int main()
{
    S s;
    return s.g();
}

This fails to compile with the error:

error: cannot call member function 'int S::f()' without object

Trying this->f() doesn't work either, as this may not be used in that context.

Is there a way to make this work, still using the default argument?


Of course it can be worked around by not using default arguments at all:

int g(int arg) { return arg; }
int g() { return g(f()); }

however that gets verbose considering that in the "real code" there are more parameters before arg, and several functions following this pattern. (And even more ugly if there were multiple default arguments in the one function).

NB. This question looks similar at first, but in fact he is asking how to form a closure, which is a different problem (and the linked solution doesn't apply to my situation).


Solution

  • You can only use members there if they are static. From a C++11 draft standard (n3299), §8.3.6/9:

    Similarly, a non-static member shall not be used in a default argument, 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).

    E.g., this works:

    struct S {
      static int f() { return 1; }
      int g(int arg = f()) { return arg; }
    };
    
    int main()
    {
      S s;
      return s.g();
    }
    

    This also works (I think that's what the first expression means):

    struct S {
      int f() { return 42; }
      int g(int arg);
    };
    
    static S global;
    
    int S::g(int arg = global.f()) { return arg; }
    
    int main()
    {
      S s;
      return s.g();
    }
    

    As for this, it is indeed not allowed (§8.3.6/8):

    The keyword this shall not be used in a default argument of a member function.

    The default arguments page on cppreference.com has a lot of details regarding the subject—it can get quite complex.