【发布时间】:2018-10-12 09:26:42
【问题描述】:
编辑:
显然,GCC 允许实例化没有参数列表的类模板(当参数默认时),这是不合规的(Clang 是合规的)。
我猜测需要括号的原因(即使参数列表为空)是为了明确表明它是模板实例化,而不是实际类型。
因此,我将最初的问题转向类模板和函数模板案例之间的差异:为什么在第二个 sn-p 中允许调用不带括号的 a,而在第一个 sn-p 中实例化 A ?为什么b不允许呢?
原文:
一个只有默认参数的类模板可以在没有任何参数列表的情况下实例化(参见下面的 A)。
但是,如果该类模板的别名通过 using 声明定义为具有相同默认参数的模板(请参见下面的 B),则其实例化需要一个参数列表(可能为空)。
类似地,将类模板的别名定义为实际类型(参见下面的 C)需要一个参数列表(同样,可能为空)。
这背后有什么原因吗?
template<int i = 1>
struct A {
operator int() { return i; }
};
template<int i = 2>
using B = A<i>;
// using C = A; <-- error: missing template arguments after 'A'
using C = A<>;
int main() {
A a; // Edit: Actually should require brackets: A<> a;
// B b; <-- error: missing template arguments before 'b'
B<> b;
C c;
}
我尝试过用函数模板而不是类模板构建类似的场景,最后一种情况(C)略有不同:如果在@的定义中指定了返回类型,则不需要参数列表987654325@。我想我明白为什么,但我欢迎一些见解。否则,这两种情况都类似于类模板的情况。
template<int i = 1>
auto a() { return i; }
// auto a() -> int { return i; }
// if the return type is specified, c can be defined as commented below
template<int i = 2>
auto b = a<i>;
// auto c = a; <-- error: unable to deduce 'auto' from 'a'
auto c = a<>;
int main() {
a();
// b(); <-- error: missing template arguments before '(' token
b<>();
c();
}
此外,现代 C++ 标准(C++11 到 C++20)之间是否存在显着差异?我最感兴趣的是 C++17 案例,但我很想知道这些事情是否已经改变,或者将会改变。
据我所知,在 C++14 中,类模板实例化无论如何都需要参数列表,而函数模板调用则不需要。而且我还没有发现 C++17 和 C++2a 与 GCC 之间的区别。
【问题讨论】:
-
Coliru 使用了一个稍微过时的clang(5.0.0,最新版本是7.0.0),它没有实现一些关于CTAD的缺陷报告。
-
@cpplearner 我不太明白这应该影响哪一部分。 Clang 似乎符合我的要求?
-
哪个clang、clang 5.0.0或clang 7.0.0(允许
A a;)? -
@cpplearner 哦,所以 Clang 7.0.0 允许和 GCC 一样,不合规?这只是两个编译器为了方便而添加的东西,还是两者都有错误?还是实际上应该被标准允许?
标签: c++ templates language-lawyer c++17