为什么在指定模板 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
不是类型。 C
和 C<>
不是一回事。对于拥有所有默认模板参数,过去和现在都没有特别考虑。类型和 class 模板是不同的,并且继续被区别对待。
在指定模板 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).
但是 显然,此限制已在 Kona 中取消,因此 C c;
不包含 初始化器 ,因此它在语法上不合适。这是允许这样做的 gcc 错误。尽管明确禁止这一点似乎很奇怪。C c;
在 C++17 中确实是良构的。一旦有新的措辞出现,我会更新答案。
在 C++17 之前,语句格式错误只是因为 C
不是类型。 C
和 C<>
不是一回事。对于拥有所有默认模板参数,过去和现在都没有特别考虑。类型和 class 模板是不同的,并且继续被区别对待。