Nicer syntax for setting default argument value to default constructor

Yes:

void foo(a::really::long::type::name arg = {});

To sum up the following standard definitions:

This is list initialization. Depending of the type, aggregate initialization is performed or the object is value initialized, which in turn implies default initialized or zero initialized.

Some “corner” cases are when the type is a specialization of std::initializer_list or when the type has a std::initializer_list constructor (it is called if it has no default constructor)


The relevant standard quotes (in order we encounter definitions):

§8.3.6 Default arguments [dcl.fct.default]

1 If an initializer-clause is specified in a parameter-declaration this
initializer-clause is used as a default argument

5 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 (8.5)

§8.5.4 List-initialization [dcl.init.list]

1 List-initialization is initialization of an object or reference from a braced-init-list. Such an initializer is called an initializer
list, […]. An initializer list may be empty. List-initialization can
occur in direct-initialization or copy initialization contexts;
[..] list-initialization in a
copy-initialization context is called copy-list-initialization.

3 List-initialization of an object or reference of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed (8.5.1)
  • Otherwise, if the initializer list has no elements and T is a class
    type with a default constructor, the object is value-initialized.
  • Otherwise, if T is a specialization of std::initializer_list, a prvalue initializer_list object is constructed as described below and
    used to initialize the object according to the rules for
    initialization of an object from a class of the same type (8.5).
  • Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7) […]
  • Otherwise, if the initializer list has no elements, the object is value-initialized.

§ 8.5 Initializers [dcl.init]

8 To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) or a default constructor that is
    user-provided or deleted, then the object is default-initialized;
  • if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized
    and the semantic constraints for default-initialization are checked,
    and if T has a non-trivial default constructor, the object is
    default-initialized;
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized

7 To default-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9), the default constructor (12.1) for T is called (and the initialization is
    ill-formed if T has no default constructor or overload resolution
    (13.3) results in an ambiguity or in a function that is deleted or
    inaccessible from the context of the initialization);
  • if T is an array type, each element is default-initialized;
  • otherwise, no initialization is performed.

6 To zero-initialize an object or reference of type T means:

  • if T is a scalar type (3.9), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;
  • if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is
    zero-initialized and padding is initialized to zero bits;
  • if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero-initialized and padding is
    initialized to zero bits;
  • if T is an array type, each element is zero-initialized;
  • if T is a reference type, no initialization is performed.

§13.3.1.7 Initialization by list-initialization [over.match.list]

1 When objects of non-aggregate class type T are list-initialized
(8.5.4), overload resolution selects the constructor in two phases:

  • Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of
    the initializer list as a single argument.
  • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all
    the constructors of the class T and the argument list consists of the
    elements of the initializer list.

If the initializer list has no elements and T has a default
constructor, the first phase is omitted. […]

Leave a Comment