c++ - 为什么 <> 在指定一个所有模板参数都有默认值的模板类时是必需的?

标签 c++ templates c++17

<> 有充分的理由吗?在指定一个所有模板参数都有默认值的模板类时是必需的吗?

例如

#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++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<>不是一回事。对于拥有所有默认模板参数,过去和现在都没有特别考虑。类型和类模板是不同的,并且继续被区别对待。

关于c++ - 为什么 <> 在指定一个所有模板参数都有默认值的模板类时是必需的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42670137/

相关文章:

c++ - 模板类链表插入错误

c++ - 在存在不可预测的类型别名的情况下如何处理显式模板实例化?

c++ - 使用函数指针作为模板方法的默认参数时出错

c++ - 条件变量虚假唤醒/循环任务

c++ - 为什么我收到错误: “there is more than one default constructor” ?

c++ - 使用 `-> decltype` 推断返回类型

c++ - 在 C++ 类的每个成员之前是可接受的用法访问说明符

c++ - 你能用折叠表达式实现 fn(x1 ^ fn(x0)) 吗?

c++ - 在 C++ 中格式化文本

c++ - 尝试使用 Redispp 在类中设置全局 Redis 连接