用大括号括起来的初始化列表初始化 class
Initialize a class with brace-enclosed initializer list
我正在尝试用大括号括起来的初始化列表来初始化 class 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;
}
所有这些初始化(和赋值)都应该有效。 (加上自定义默认构造函数。因此不可能使用聚合 class。)
虽然我可以像这样使用 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 给出错误 "could not convert '{1, 2, 3}' from '' to 'Vec<3u>'")
我不明白为什么其中一个初始化应该起作用,而另一个却不行。
关于如何使用大括号括起来的初始值设定项列表,同时确保编译时的正确长度,还有其他想法吗?
谢谢:)
初始化列表更适用于列表大小是动态的情况。在您的情况下, 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}};
你需要两对括号:
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}};
}
我正在尝试用大括号括起来的初始化列表来初始化 class 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;
}
所有这些初始化(和赋值)都应该有效。 (加上自定义默认构造函数。因此不可能使用聚合 class。)
虽然我可以像这样使用 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 给出错误 "could not convert '{1, 2, 3}' from '' to 'Vec<3u>'")
我不明白为什么其中一个初始化应该起作用,而另一个却不行。 关于如何使用大括号括起来的初始值设定项列表,同时确保编译时的正确长度,还有其他想法吗?
谢谢:)
初始化列表更适用于列表大小是动态的情况。在您的情况下, 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}};
你需要两对括号:
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}};
}