C++ 非类型模板参数不能具有类型
对于将来遇到这个问题的人来说,最初的问题是:如何从中获得最简单的示例点,以便使用GCC或CLANG进行编译 edit1显示了可能最小的代码,该代码使用CLANG失败,但使用GCC编译,并且使用-std=c++2a。 edit2显示了进一步添加的代码,这也破坏了GCC。 这篇文章的作者好心地评论了为什么这还不起作用,谢谢你,巴里 编辑1: 以下简化代码适用于gcc 9.3.0,但不适用于clang 10.0.0:C++ 非类型模板参数不能具有类型,c++,c++20,C++,C++20,对于将来遇到这个问题的人来说,最初的问题是:如何从中获得最简单的示例点,以便使用GCC或CLANG进行编译 edit1显示了可能最小的代码,该代码使用CLANG失败,但使用GCC编译,并且使用-std=c++2a。 edit2显示了进一步添加的代码,这也破坏了GCC。 这篇文章的作者好心地评论了为什么这还不起作用,谢谢你,巴里 编辑1: 以下简化代码适用于gcc 9.3.0,但不适用于clang 10.0.0: struct Point {
struct Point {
int x = 0;
int y = 0;
};
template <Point> // ok in C++20
void takes_tmpl_point();
int main()
{
// EMPTY
}
test.cpp:6:16: error: a non-type template parameter cannot have type 'Point'
template <Point> // ok in C++20
^
test.cpp:11:21: error: expected expression
takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
^
2 errors generated.
编辑2:
根据作者的说法,由于编译器稍微落后于标准,原始代码到目前为止还不能在GCC或CLANG上工作。原始代码如下:
struct Point {
int x = 0;
int y = 0;
};
template <Point> // ok in C++20
void takes_tmpl_point();
int main()
{
takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
}
这将导致GCC 9.3上出现以下编译错误:
test.cpp: In function ‘int main()’:
test.cpp:11:35: error: no matching function for call to ‘takes_tmpl_point<{1, 2}>()’
11 | takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
| ^
test.cpp:7:6: note: candidate: ‘template<Point <anonymous> > void takes_tmpl_point()’
7 | void takes_tmpl_point();
| ^~~~~~~~~~~~~~~~
test.cpp:7:6: note: template argument deduction/substitution failed:
test.cpp:11:35: error: could not convert ‘{1, 2}’ from ‘<brace-enclosed initializer list>’ to ‘Point’
11 | takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
| ^
以及clang 10.0.0上的以下错误:
struct Point {
int x = 0;
int y = 0;
};
template <Point> // ok in C++20
void takes_tmpl_point();
int main()
{
// EMPTY
}
test.cpp:6:16: error: a non-type template parameter cannot have type 'Point'
template <Point> // ok in C++20
^
test.cpp:11:21: error: expected expression
takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
^
2 errors generated.
使用的编译器:
叮当声:叮当声版本10.0.0-4ubuntu1
gcc:gcc Ubuntu 9.3.0-10ubuntu2 9.3.0
Clang只是还没有将类类型实现为非类型模板参数,请参见中的P1907 gcc确实实现了它们,但实际上这里有一个问题。的语法实际上不允许使用大括号的init列表。这是一个明显的语言缺陷,以前从来没有理由拥有这样的东西,但现在肯定没有理由不拥有它。目前这是一个语言错误。尽管如此,gcc还是支持将带括号的init列表作为模板参数。。。只是不是指定的初始值设定项列表 所以我的博客文章比实际语言快了一点。。。直到语言流行起来,即使技术上不支持:
takes_tmpl_point<{.x=1, .y=2}>();
这绝对是正确的:
takes_tmpl_point<Point{.x=1, .y=2}>();
Clang只是还没有将类类型实现为非类型模板参数,请参见中的P1907 gcc确实实现了它们,但实际上这里有一个问题。的语法实际上不允许使用大括号的init列表。这是一个明显的语言缺陷,以前从来没有理由拥有这样的东西,但现在肯定没有理由不拥有它。目前这是一个语言错误。尽管如此,gcc还是支持将带括号的init列表作为模板参数。。。只是不是指定的初始值设定项列表 所以我的博客文章比实际语言快了一点。。。直到语言流行起来,即使技术上不支持:
takes_tmpl_point<{.x=1, .y=2}>();
这绝对是正确的:
takes_tmpl_point<Point{.x=1, .y=2}>();
确定:您的编译器是否声明符合所有C++20?GCC 9.3适用于您最近的示例。确定:您的编译器是否声明符合所有C++20?GCC 9.3适用于您最近的示例。谢谢Barry!所以你的博客讨论了该语言的工作原理,但编译器却在后面松懈,明白了吗!有没有办法让它在当前的限制下工作?我真的很喜欢这种风格。。。谢谢你的回复@FernandoJeronymo你做不到的事情需要考虑到一点;但你可以做到这一点;您只需要命名类型。您的命名在这里有点反习惯用法:struct type_t{using type=t;。在STL中,_t-suffix用于::类型成员,而不是这些成员的容器。@BIPL在标准库中有大量以_t:,,,,结尾的类型。更不用说像[u]这样的整数类型了intN\u t、uintptr\u t等@Barry可以是标量的也可以是空的。谢谢Barry!所以你的博客讨论了该语言的工作方式,但编译器在后面松懈了,明白了吗!有没有办法让它在当前的限制下工作?我真的很喜欢这种风格…谢谢你的回复!@FernandoJeronymo你不能这么做,但你可以o需要指出的是,您只需要命名类型。在我看来,您的命名有点反习惯用法:struct type_t{using type=t;。在STL中,_t-suffix用于::类型成员,而不是这些成员的容器。@BIPL标准库中有大量类型以_t:,,,结尾。更不用说像[u]这样的整数类型了intN\u t、uintptr\u t等@Barry要么是标量,要么是空的,是的。