收录日期:2020/11/30 15:25:46 时间:2010-09-07 20:27:37 标签:c++

what does standard say about such case:

template<class C>
struct A {
    A(C c = C());
};

struct C {
    C(int);
};

A<C> a(C(1));

btw, Comeau does not raise error.

If you don't use the default argument (that is, you supply a value), then it is not instantiated at all.

14.7.1/2:

Unless a function template specialization has been explicitly instantiated or explicitly specialized, the func- tion template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist. Unless a call is to a function template explicit specialization or to a member function of an explicitly specialized class template, a default argument for a function template or a member function of a class template is implicitly instantiated when the function is called in a context that requires the value of the default argument.

What a mouthful. Actually, default arguments of both functions and templates have specific instantiation rules all to themselves.

If the default argument is never used, then this is fine, as its never actually evaluated by the compiler until it is used. However, as soon as you use the default argument such as:

A<C> a;

you should get a compile error.

I am not sure on what your dilemma is. If you are wondering how the template can be instantiated when there is no default constructor, that is fine. The defaulted first argument of the template constructor is only required if no argument is provided. The compiler is happy with C not having a default constructor as it does not need to use it.

On the other hand, if you tried

A<C> a;

The compiler would have to match the constructor call to A<C>::A( C ) with the default argument C(), and that will trigger a compile time error as the type C does not have a default constructor.

The actual quote from the standard is from §14.7.1[temp.inst]/11:

If a function template f is called in a way that requires a default argument expression to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument expression is done as if the default argument expression had been an expression used in a function template specialization with the same scope, the same template parameters and the same access as that of the function template f used at that point. This analysis is called default argument instantiation. The instantiated default argument is then used as the argument of f.

There is an actual example in the next paragraph §14.7.1[temp.inst]/12:

Each default argument is instantiated independently. [Example:

template<class T> 
void f(T x, T y = ydef(T()), T z = zdef(T()));
class A { }; 
A zdef(A);
void g(A a, A b, A c) { 
   f(a, b, c);         // no default argument instantiation
   f(a, b);            // default argument z = zdef(T()) instantiated
   f(a);               // ill-formed; ydef is not declared
}

—end example]