例如
#include <array>
class Range
{
public:
Range(std::array<float, 2> ends) : m_ends(ends) {}
private:
std::array<float, 2> m_ends;
};
我可以
Range r({1, 2});
现在我有另一个班级
class Box
{
public:
Box(std::array<Range, 3> ranges) : m_ranges(ranges) {}
private:
std::array<Range, 3> m_ranges;
};
我希望我能做到以下
Box b({{1,2}, {3,4}, {5,6}});
但我不能。如何更改代码以使其成为可能。
答案 0 :(得分:4)
std::array
有点奇怪。它没有用户定义的构造函数,所以它很像一个普通的结构。所以std::array<float,2>
很像
struct two_floats {
float array[2];
};
因此,如果你初始化一个,你会在逻辑上这样做:
two_floats x = {{1,2}};
std::array<float,2> y = {{1,2}};
外部大括号用于结构本身,内部大括号用于结构的内容。
恰好只能提供一组大括号:
two_floats x = {1,2};
但这是由于C ++中的特殊规则允许在某些情况下省略大括号。类似于如何使用一组大括号初始化二维数组:
float x[2][2] = {1,2,3,4};
这就是你初始化你的范围时发生的事情:
Range r({1, 2});
相当于
std::array<float,2> arg = {1,2}; // one set of braces omittted
Range r(arg);
但哪个更明确地写成:
std::array<float,2> arg = {{1,2}};
Range r(arg);
初始化Box时会发生类似的事情。如果我们明确写出初始化,它将如下所示:
std::array<float,2> box_arg1 = {{1,2}};
std::array<float,2> box_arg2 = {{3,4}};
std::array<float,2> box_arg3 = {{5,6}};
std::array<Range,3> box_args = {{box_arg1,box_arg2,box_arg3}};
Box b(box_args);
因此,如果我们替换初始化器,我们得到:
Box b({{{{1,2}},{{3,4}},{{5,6}}}});
这是有效的。但它非常丑陋。这个初始化太复杂了,不允许在这里省略额外的括号,这就是你遇到的问题。
解决此问题的一种方法是提供其他构造函数来获取各个数组元素。
class Range
{
public:
Range(float x,float y) : m_ends{x,y} { }
Range(std::array<float, 2> ends) : m_ends(ends) {}
private:
std::array<float, 2> m_ends;
};
class Box
{
public:
Box(Range x,Range y,Range z) : m_ranges{x,y,z} {}
Box(std::array<Range, 3> ranges) : m_ranges(ranges) {}
private:
std::array<Range, 3> m_ranges;
};
现在你可以像你原来想要的那样初始化你的Box:
Box b({{1,2}, {3,4}, {5,6}});
答案 1 :(得分:3)
我只是删除数组并使用通常的字段。如果确实需要,您可以随时添加operator[]
重载。只需将字段名称更改为您实际建模的内容。
class Range
{
public:
Range(float x, float y) : m_x{x}, m_y{y}
{}
private:
float m_x, m_y;
};
class Box
{
public:
Box(Range w, Range h, Range d) : m_w{w}, m_h{h}, m_d{d}
{}
private:
Range m_w, m_h, m_d;
};
答案 2 :(得分:1)
<强>问题强>
此代码:Box b({{1,2}, {3,4}, {5,6}});
正在尝试Range
个Range
个实例,即使Range
不是聚合。
聚合初始化是列表初始化的一种形式,其中 初始化聚合
聚合是以下类型之一:
数组类型
类类型(通常是struct或union),具有
无 私有或受保护的非静态数据成员
没有用户提供的构造函数,包括从公共基础继承的那些 (从C ++ 17开始)(允许显式默认或删除构造函数)
(自C ++ 11以来)没有虚拟,私有或受保护(自C ++ 17)基础 课程
没有虚拟成员函数
<强>解决方案强>
显式调用std::array
的构造函数,只聚合初始化Box b({Range({1,2}), Range({3,4}), Range({5,6})});
:
{{1}}
答案 3 :(得分:1)
您可以使用初始化列表:
class Range
{
public:
Range(std::initializer_list<float> ends) : m_ends(ends) {}
float a() {
return m_ends[0];
}
float b() {
return m_ends[1];
}
private:
std::vector<float> m_ends;
};
class Box
{
public:
Box(std::initializer_list<Range> ranges) : m_ranges(ranges) {}
void print()
{
for (auto& i : m_ranges)
{
std::cout << i.a() << "," << i.b() << std::endl;
}
}
private:
std::vector<Range> m_ranges;
};
Range r({ 1,2 });
Box b({ {1,2},{3,4},{5,6} });
b.print();
给出
1,2
3,4
5,6
答案 4 :(得分:0)
AFAIK无法用数组完成,你必须求助于基本类型
struct Range
{
float m_ends[2] ;
};
Range r = {1.0f, 2.0f};
struct Box
{
Range m_ranges[3];
};
Box b = {{{1.0f, 2.0f}, {1.0f, 2.0f}, {1.0f, 2.0f}}};
答案 5 :(得分:0)
要获得正确的初始化列表,请先列出其完整格式:
Box b{
array<Range, 3>{{ // std::array needs aggregate-initialize,
// and have to initialize a inner array
// without a addition '{', C++ is unable to
// know that the inner element is Range
Range{
{1, 2} // short-hand for array<float>{{3, 4}}
},
Range{
{3, 4}
},
Range{
{5, 6}
}
}}
}
删除Box
以外的所有类型,我们得到了:
Box b{ {{ {{1, 2}}, {{3, 4}}, {{5, 6}} }} }