8 Declarators [dcl.decl]

8.3 Meaning of declarators [dcl.meaning]

8.3.6 Default arguments [dcl.fct.default]

If an initializer-clause is specified in a parameter-declaration this initializer-clause is used as a default argument. Default arguments will be used in calls where trailing arguments are missing.

Example: the declaration

void point(int = 3, int = 4);

declares a function that can be called with zero, one, or two arguments of type int. It can be called in any of these ways:

point(1,2);  point(1);  point();

The last two calls are equivalent to point(1,4) and point(3,4), respectively.  — end example ]

A default argument shall be specified only in the parameter-declaration-clause of a function declaration or in a template-parameter ([temp.param]); in the latter case, the initializer-clause shall be an assignment-expression. A default argument shall not be specified for a parameter pack. If it is specified in a parameter-declaration-clause, it shall not occur within a declarator or abstract-declarator of a parameter-declaration.103

For non-template functions, default arguments can be added in later declarations of a function in the same scope. Declarations in different scopes have completely distinct sets of default arguments. That is, declarations in inner scopes do not acquire default arguments from declarations in outer scopes, and vice versa. In a given function declaration, each parameter subsequent to a parameter with a default argument shall have a default argument supplied in this or a previous declaration or shall be a function parameter pack. A default argument shall not be redefined by a later declaration (not even to the same value). [ Example:

void g(int = 0, ...);           // OK, ellipsis is not a parameter so it can follow
                                // a parameter with a default argument
void f(int, int);
void f(int, int = 7);
void h() {
  f(3);                         // OK, calls f(3, 7)
  void f(int = 1, int);         // error: does not use default
                                // from surrounding scope
void m() {
  void f(int, int);             // has no defaults
  f(4);                         // error: wrong number of arguments
  void f(int, int = 5);         // OK
  f(4);                         // OK, calls f(4, 5);
  void f(int, int = 5);         // error: cannot redefine, even to
                                // same value
void n() {
  f(6);                         // OK, calls f(6, 7)

 — end example ] For a given inline function defined in different translation units, the accumulated sets of default arguments at the end of the translation units shall be the same; see [basic.def.odr]. If a friend declaration specifies a default argument expression, that declaration shall be a definition and shall be the only declaration of the function or function template in the translation unit.

The default argument has the same semantic constraints as the initializer in a declaration of a variable of the parameter type, using the copy-initialization semantics ([dcl.init]). The names in the default argument are bound, and the semantic constraints are checked, at the point where the default argument appears. Name lookup and checking of semantic constraints for default arguments in function templates and in member functions of class templates are performed as described in [temp.inst]. [ Example: in the following code, g will be called with the value f(2):

int a = 1;
int f(int);
int g(int x = f(a));            // default argument: f(::a)

void h() {
  a = 2;
  int a = 3;
  g();                          // g(f(::a))

 — end example ] [ Note: In member function declarations, names in default arguments are looked up as described in [basic.lookup.unqual]. Access checking applies to names in default arguments as described in Clause [class.access].  — end note ]

Except for member functions of class templates, the default arguments in a member function definition that appears outside of the class definition are added to the set of default arguments provided by the member function declaration in the class definition; the program is ill-formed if a default constructor ([class.ctor]), copy or move constructor, or copy or move assignment operator ([class.copy]) is so declared. Default arguments for a member function of a class template shall be specified on the initial declaration of the member function within the class template. [ Example:

class C {
  void f(int i = 3);
  void g(int i, int j = 99);

void C::f(int i = 3) {          // error: default argument already
}                               // specified in class scope
void C::g(int i = 88, int j) {  // in this translation unit,
}                               // C::g can be called with no argument

 — end example ]

Local variables shall not be used in a default argument. [ Example:

void f() {
  int i;
  extern void g(int x = i);     //error
  // ...

 — end example ]

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

class A {
  void f(A* p = this) { }       // error

 — end example ]

A default argument is evaluated each time the function is called with no argument for the corresponding parameter. 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. [ Example:

int a;
int f(int a, int b = a);            // error: parameter a
                                    // used as default argument
typedef int I;
int g(float I, int b = I(2));       // error: parameter I found
int h(int a, int b = sizeof(a));    // error, parameter a used
                                    // in default argument

 — end example ] 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 ([expr.ref]) or unless it is used to form a pointer to member ([expr.unary.op]). [ 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 [class].  — end example ] A default argument is not part of the type of a function. [ Example:

int f(int = 0);

void h() {
  int j = f(1);
  int k = f();                  // OK, means f(0)

int (*p1)(int) = &f;
int (*p2)() = &f;               // error: type mismatch

 — end example ] When a declaration of a function is introduced by way of a using-declaration ([namespace.udecl]), any default argument information associated with the declaration is made known as well. If the function is redeclared thereafter in the namespace with additional default arguments, the additional arguments are also known at any point following the redeclaration where the using-declaration is in scope.

A virtual function call ([class.virtual]) uses the default arguments in the declaration of the virtual function determined by the static type of the pointer or reference denoting the object. An overriding function in a derived class does not acquire default arguments from the function it overrides. [ Example:

struct A {
  virtual void f(int a = 7);
struct B : public A {
  void f(int a);
void m() {
  B* pb = new B;
  A* pa = pb;
  pa->f();          // OK, calls pa->B::f(7)
  pb->f();          // error: wrong number of arguments for B::f()

 — end example ]

This means that default arguments cannot appear, for example, in declarations of pointers to functions, references to functions, or typedef declarations.