例如
#include <iostream> template<typename T = int> class C { public: T obj = 0; }; int main() { C c1; // Error on almost all compilers (see note below) C<> c2; std::cout << c1.obj << " " << c2.obj << std::endl; return 0; }
这样做的一个示例缺点是,如果您有一个已经在各个地方使用的类,并且您稍后将其重构为具有其模板参数的默认参数的类模板,那么您必须添加<>在所有使用该课程的地方.
注意:它看起来像GCC最新的HEAD(7.0.1)accepts语法没有<>.早期版本没有,也没有任何版本的Clang.这是最新的GCC HEAD中的错误吗?或者也许C 17的标准现在接受没有<>的语法而GCC就在这里?
解决方法
C c1{};
由于deduction for class templates.我们为每个构造函数(和演绎指南)合成一个函数并执行重载解析:
template <class T=int> C<T> foo(); template <class T=int> C<T> foo(C<T> const&); template <class T=int> C<T> foo(C<T>&&);
第一个是可行的重载,而另外两个不是,因此推断成功并且占位符C被推断的类型C< int>替换.
但是,在语法上,[dcl.type.class.deduct]中需要初始值设定项:
If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of a simple-declaration,the init-declarator of that declaration shall be of the form:
declarator-id attribute-specifier-seqopt initializer
The placeholder is replaced by the return type of the function selected by overload resolution for class
template deduction (13.3.1.8).
但是C c;不包含初始化程序,因此它不符合语法.这是允许这个的gcc错误.虽然特别禁止这一点似乎很奇怪.显然,这种限制已在科纳解除,所以C c;确实在C17中形成了良好的形式.一旦出现新的措辞,我将更新答案.
在C 17之前,该陈述仅仅因为C不是一种类型而形成不良. C和C< C>不是一回事.拥有所有默认模板参数已经并且仍然没有特别考虑.类型和类模板是不同的,并继续区别对待.