std :: array构造函数继承

ony*_*ony 12 c++ c++11

我正在尝试获得std::array数学向量的扩展变体(并公开相同的接口,array没有样板代码).我知道std::valarray但我想要固定大小以便在矩阵乘法中正确输入.因此我array非常适合.但是当我尝试继承构造函数时,它失败了.

struct vec2d : std::array<float, 2>
{ using array::array; }; // simplified

struct vec : std::vector<float>
{ using vector::vector; };

std::array<float, 2> x = {1, 2};
vec y = {1, 2};
vec2d z = {1, 2}; // error: could not convert ‘{1, 2}’ 
                  //        from ‘<brace-enclosed initializer list>’ to ‘vec2d’
Run Code Online (Sandbox Code Playgroud)

针对GCC 4.8.2和clang 3.4报告了此错误.最后说vec2d只有隐式默认/复制/移动构造函数.是的,array只有隐含的构造函数在违背vector其从构造函数initializer_list.但是由于ctors是继承的,因此继承初始化它的可能性与初始化相同array.

问题:为什么我们有错误而不是预期的行为(类似于array初始化)?

注意:我可以手动编写转发以使其工作,但这看起来不像ctor继承那么优雅.

struct vec2d : std::array<float, 2>
{
    using array::array;
    // nasty boilerplate code I don't want to have in C++11
    template <typename... Args>
    vec2d(Args &&... args) : array({float(std::forward<Args>(args))...}) {}
};  
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 11

std::array 被设计为聚合,因此它故意不定义任何构造函数.

不幸的是,这意味着不可能继承它并获得相同的行为,因为聚合不能有基类.

为什么你还需要继承std::array呢?你打算加入任何私人会员吗?如果没有,那么你可以围绕运行的自由函数构建你的框架std::array,或者也许是一个typedef.

如果你真的想继承std::array,你将不得不接受失去聚合状态并提供你想要的任何构造函数.


请注意,上面的答案仅适用于C++ 11和C++ 14.在C++ 17中,聚合的定义被放宽以允许公共基类,因此只需从代码中派生std::array和删除using声明就可以使代码编译:

struct vec2d : std::array<float, 2>
{ }; // simplified

std::array<float, 2> x = {1, 2};
vec2d z = {1, 2};
Run Code Online (Sandbox Code Playgroud)

[实例]

  • @ony:从一个不是为了继承的类继承而来也是尴尬的,并且总的来说不赞成. (4认同)