我需要定义一个接受多个 3D 坐标作为参数的 C++ 模板。当这些坐标的所有维度都定义为单独的整数变量时,参数列表将变得非常长 - 3 个坐标需要 9 个参数,这使得模板难以使用。
因此,非常希望以使用编译时数组的方式声明模板。它们的默认参数也应该直接在模板声明的位置声明为值,而不是变量名。
经过一些实验,令我惊讶的是,我发现 GCC 13 将接受以下 C++ 程序std=c++20
:
#include <cstdio>
#include <array>
template <
std::array<int, 3> offset = {0, 0, 0}
>
struct Array
{
void operator() (int i, int j, int k)
{
printf("(%d, %d, %d)\n", i + offset[0], j + offset[1], k + offset[2]);
}
};
int main(void)
{
Array arr_default;
arr_default(0, 0, 0);
Array<{1, 1, 1}> arr;
arr(0, 0, 0);
return 0;
}
然而,clang 18 拒绝使用braced-init-list,因为它无效:
test2.cpp:5:30: error: expected expression
5 | std::array<int, 3> offset = {0, 0, 0}
| ^
test2.cpp:17:8: error: no viable constructor or deduction guide for deduction of template arguments of 'Array'
17 | Array arr_default;
| ^
test2.cpp:7:8: note: candidate template ignored: couldn't infer template argument 'offset'
7 | struct Array
| ^
test2.cpp:7:8: note: candidate function template not viable: requires 1 argument, but 0 were provided
7 | struct Array
| ^~~~~
test2.cpp:20:8: error: expected expression
20 | Array<{1, 1, 1}> arr;
| ^
3 errors generated.
问题
它真的是合法的C++程序吗?如果是,我应该使用什么语法来说服 clang 接受它?如果不是,我是否应该报告 GCC 错误以毫无疑问地接受它?
是否有替代且更兼容的方式来实现我的目标?
std::array
不必使用,任何其他具有同等效果的方法也可以。
问题
这是CWG 2450和/或CWG 2049,尽管当前语法不允许这样做,但由于下述原因建议允许/有效。这意味着,Gcc 只是抢先允许语法。来自 CWG 2450:
(强调我的)
如果您想知道当前语法如何不允许这样做,来自temp.name#1:
并且由于不是上面列出的三个构造中的任何一个,因此根据当前语法
{1, 1, 1}
规则,它不能用作模板参数。解决方案
您可以在花括号初始化列表之前显式编写,
std::array
如下所示:笔记
另请注意,clang trunk也开始接受该程序,而 gcc 和 msvc 已经从早期版本接受了该程序。
在当前的 C++ 中,我希望你的代码看起来像这样: