非类型模板参数不能有类型
a non-type template parameter cannot have type
对于以后遇到这个问题的任何人,最初的问题是:"How to get the simplest example (Point) from this article to compile with GCC or CLANG?"
- 编辑 1 显示了使用 CLANG 失败但使用 GCC 编译(均使用 -std=c++2a)的最小可能代码。
- 编辑 2 显示添加了更多代码,这也破坏了 GCC。
文章的作者 (@BarryRevzin) 很友好地评论了为什么这还行不通的原因,谢谢巴里!
编辑 1:
下面的简化代码适用于 gcc 9.3.0,但不适用于 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
}
编辑 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 上出现以下错误:
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.
使用的编译器:
- clang: clang 版本 10.0.0-4ubuntu1
- gcc: gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0
Clang 还没有将 class 类型实现为非类型模板参数,请参阅 this table 中的 P1907。
gcc 确实实现了它们,但这里实际上存在一个问题。 template-argument doesn't actually allow for a braced-init-list. This is a clear language defect (there was never a reason to have such a thing before P1907 的语法,但现在肯定没有理由 不 拥有它)。目前这是一个语言错误。尽管如此,gcc 继续前进并支持 braced-init-list 作为模板参数……只是不支持 designated-initializer-list。
所以我的博客 post 比实际语言 运行 领先一点...直到语言赶上来,即使这在技术上不受支持:
takes_tmpl_point<{.x=1, .y=2}>();
这绝对有效:
takes_tmpl_point<Point{.x=1, .y=2}>();
对于以后遇到这个问题的任何人,最初的问题是:"How to get the simplest example (Point) from this article to compile with GCC or CLANG?"
- 编辑 1 显示了使用 CLANG 失败但使用 GCC 编译(均使用 -std=c++2a)的最小可能代码。
- 编辑 2 显示添加了更多代码,这也破坏了 GCC。
文章的作者 (@BarryRevzin) 很友好地评论了为什么这还行不通的原因,谢谢巴里!
编辑 1:
下面的简化代码适用于 gcc 9.3.0,但不适用于 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
}
编辑 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 上出现以下错误:
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.
使用的编译器:
- clang: clang 版本 10.0.0-4ubuntu1
- gcc: gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0
Clang 还没有将 class 类型实现为非类型模板参数,请参阅 this table 中的 P1907。
gcc 确实实现了它们,但这里实际上存在一个问题。 template-argument doesn't actually allow for a braced-init-list. This is a clear language defect (there was never a reason to have such a thing before P1907 的语法,但现在肯定没有理由 不 拥有它)。目前这是一个语言错误。尽管如此,gcc 继续前进并支持 braced-init-list 作为模板参数……只是不支持 designated-initializer-list。
所以我的博客 post 比实际语言 运行 领先一点...直到语言赶上来,即使这在技术上不受支持:
takes_tmpl_point<{.x=1, .y=2}>();
这绝对有效:
takes_tmpl_point<Point{.x=1, .y=2}>();