为什么在指定模板 class 时需要 <>,它的所有模板参数都有默认值?

Why is <> required when specifying a template class which has defaults for all its template parameters?

在指定模板 class 时需要 <> 是否有充分的理由,该模板的所有模板参数都有默认值?

例如

#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;
}

这样做的一个缺点是,如果您有一个已在不同地方使用的 class,并且您稍后将其重构为一个 class 模板,其模板参数具有默认参数, 然后你必须在所有使用 class.

的地方添加 <>

注意:看起来像 GCC 最新的 HEAD (7.0.1) accepts 没有 <> 的语法。早期版本没有,任何版本的 Clang 也没有。这是最新的 GCC HEAD 中的错误吗?或者也许 C++17 的标准现在接受没有 <> 的语法,而 GCC 就在前面?

在 C++17 中,这是格式正确的:

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 错误。尽管明确禁止这一点似乎很奇怪。 显然,此限制已在 Kona 中取消,因此 C c; 在 C++17 中确实是良构的。一旦有新的措辞出现,我会更新答案。


在 C++17 之前,语句格式错误只是因为 C 不是类型。 CC<> 不是一回事。对于拥有所有默认模板参数,过去和现在都没有特别考虑。类型和 class 模板是不同的,并且继续被区别对待。