标准对此类案件的评价是什么:
template<class C>
struct A {
A(C c = C());
};
struct C {
C(int);
};
A<C> a(C(1));
顺便说一句,Comeau不会引发错误。
答案 0 :(得分:4)
如果您不使用默认参数(即提供值),则根本不会实例化。
14.7.1 / 2:
多么满口。实际上,函数和模板的默认参数都有自己的特定实例化规则。除非是功能模板 专业化已经明确 实例化或明确地 专业的功能模板 专业化是含蓄的 在专业化时实例化 在上下文中引用 需要一个函数定义 存在。除非呼叫是一个功能 模板显式专业化或 明确的成员函数 专门的类模板,默认 函数模板的参数或 类模板的成员函数是 隐式实例化的时候 函数在上下文中调用 需要默认值 参数。
答案 1 :(得分:3)
我不确定你的困境是什么。如果您想知道如何在没有默认构造函数的情况下实例化模板,那很好。只有在没有提供参数的情况下,才需要模板构造函数的默认第一个参数。编译器很满意C
没有默认构造函数,因为它不需要使用它。
另一方面,如果你试过
A<C> a;
编译器必须将对A<C>::A( C )
的构造函数调用与默认参数C()
进行匹配,这将触发编译时错误,因为类型C
没有默认构造函数
标准的实际引用来自§14.7.1[temp.inst] / 11:
如果以需要使用默认参数表达式的方式调用函数模板f,则查找从属名称,检查语义约束,并完成默认参数表达式中使用的任何模板的实例化好像默认参数表达式是在具有相同作用域的函数模板特化中使用的表达式,相同的模板参数以及与该点处使用的函数模板f相同的访问权限。此分析称为默认参数实例化。然后将实例化的默认参数用作f。
的参数
下一段§14.7.1[temp.inst] / 12:
中有一个实际的例子每个默认参数都是独立实例化的。 [实施例:
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]
答案 2 :(得分:3)
如果从未使用默认参数,那么这很好,因为编译器在使用它之前从未实际评估过它。但是,只要使用默认参数,例如:
A<C> a;
你应该收到编译错误。