繁体   English   中英

std :: array构造函数继承

[英]std::array constructor inheritance

我正在尝试为数学向量获取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’

针对GCC 4.8.2和clang 3.4报告了此错误。 最后说vec2d只有隐式的默认/复制/移动构造函数。 是的, array只有隐含的ctor,与vector ,它有来自initializer_list ctor。 但是由于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))...}) {}
};  

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};

[实例]

我有完全相同的问题,试图模仿numpy的行为。 我解决这个问题的方法是实现一个构造函数,它将std::array<float,N>作为参数(使用&&&或根据需要不带任何东西)。 然后将初始化列表自动转换为该类型,然后调用正确的构造函数。 更具体一点:

#include <array>
#include <ostream>
#include <iostream>

using namespace std;

template <int N> class Row: public array<double,N>{
    public:
        Row<N>(){}
        // this is the constructor needed
        Row<N>(array<double,N> a) : array<double,N> (a) {}
        // or, alternatively,
        // Row<N>(array<double,N>&& a) : array<double,N> (a) {}
        Row<N>(array<double,N>& a) : array<double,N> (a) {}

        // other things that may be relevant
        Row<N> operator+(Row<N>& other){
            Row<N> result;
            for(int i =0; i < N ; ++i){
                result[i] = (*this)[i] + other[i]; // notice '*'
            }
            return result;
        }
        // for lvalues
        template <int n> friend ostream& operator<<(ostream& os, Row<n>& r);
        // for rvalues
        template <int n> friend ostream& operator<<(ostream& os,Row<n>&& r);
};

// for lvalues
template <int N> ostream& operator<<(ostream& os, Row<N>& r){
    for(int i =0; i < N ; ++i) os << r[i] << "\t";
    return os;
}

// for rvalues
template <int N> ostream& operator<<(ostream& os, Row<N>&& r){
    for(int i =0; i < N ; ++i) os << r[i] << "\t";
    return os;
}

int main(){
    // here Row(array<double,3>&&) is called
    // or   Row(array<double,3>)
    Row<3> a{{1,2,3}}; // same as Row<3> a({1,2,3});
    array<double,3> arr = {1,2,3};
    Row<3> b(arr);

    cout << a << endl; // a and b are lvalues
    cout << b << endl;

    cout << (a+b) << endl; // (a+b) is a rvalue

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM