我尝试用括号括起的初始化列表初始化类Vec,在这个最小的例子中调用:
int main()
{
Vec<3> myVec1{{1,2,3}}; // or: myVec1({1,2,3});
Vec<3> myVec2;
myVec2 = {1, 2, 3};
Vec<3> myVec3 = {1,2,3};
return 0;
}
所有这些初始化(和分配)都应该有效。 (加上自定义默认构造函数。因此不可能使用聚合类。)
虽然我可以使用像这样的std :: initializer_list:
template <unsigned C>
struct Vec
{
Vec(){}
Vec(std::initializer_list<int> list)
{
//does not work for obvious reasons:
//static_assert(list.size() == C, "");
}
};
我无法静态地确保参数的数量等于我的模板参数,即{1,2,3,4}的初始化只会在运行时失败。
浏览SO,我想出了以下内容:
template <unsigned C>
struct Vec
{
Vec(){}
Vec(const unsigned(&other)[C]){}
Vec& operator=(const unsigned(&other)[C]){return *this;}
};
这适用于赋值和()或{}初始化(对于myVec1) - 但是使用=(对于myVec3)初始化失败。
(GCC提供错误&#34;无法转换&#39; {1,2,3}&#39;&#39;&#39; Vec&lt; 3u&gt;&#39 ;&#34)
我不明白为什么其中一个初始化应该起作用,而不是另一个起作用。 任何其他想法如何使用括号括起初始化列表,但也确保在编译时正确的长度?
谢谢:)
答案 0 :(得分:0)
初始化列表更适合于列表大小是动态的情况。在您的情况下,Vec
的大小是模板参数(即静态),您可能更适合使用可变参数:
template <unsigned C>
struct Vec
{
Vec(){}
template<typename ... V>
Vec(V ... args)
{
static_assert(sizeof...(V) == C, "");
//...
}
};
然后这些将起作用:
Vec<3> myVec2;
myVec2 = {1, 2, 3};
Vec<3> myVec3 = {1,2,3};
但是这个没赢,因为它明确要求std::initializer_list
:
Vec<3> myVec1{{1,2,3}};
答案 1 :(得分:0)
您需要两对括号:
Vec<3> myVec3 = {{1,2,3}};
当你这样做时:
Vec<3> myVec3 = {1, 2, 3};
// It is the same as (except that explicit constructor are not considered):
Vec<3> myVec3 = Vec<3>{1, 2, 3};'
基本上,编译器会查找Vec<3>
的构造函数,该构造函数可以是std::initializer_list
,也可以是带有3个参数的构造函数,所有参数都可以从int
构造。
如果你想要一个std::array
类似的结构,你需要创建你的类型an aggregate,这意味着它不应该有用户定义的构造函数:
template <unsigned N>
struct Vec {
int data[N];
};
void f() {
Vec<3> v1{{1, 2, 3}};
Vec<3> v2 = {{1, 2, 3}};
}