Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to get extended variant of std::array for math vectors (and expose same interface as array does without boilerplate code). I know about std::valarray but I want fixed size for proper typing in matrix multiplications. Thus I array fits perfectly. But when I try to inherit constructor it fails.

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’

This error reported for GCC 4.8.2 and for clang 3.4. Last says that vec2d have only implicit default/copy/move constructors. Yes, array have only implicit ctor in contrary to vector which have ctor from initializer_list. But since ctors are inherited it is natural to inherit possibility to initialize it in a same way as array initialized.

Question: Why we have that error instead of expected behavior (similar to array initialization)?

Note: I that I can write forwarding manually to make it work, but this doesn't look as elegant as ctor inheritance.

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))...}) {}
};  
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
378 views
Welcome To Ask or Share your Answers For Others

1 Answer

std::array is designed to be an aggregate, so it intentionally does not define any constructors.

Unfortunately, this means it's not possible to inherit from it and get the same behaviour, as aggregates cannot have base classes.

Why do you need to inherit from std::array anyway? Do you plan to add any private members? If not, then you could just build your framework around free functions operating on std::array, or perhaps a typedef to it.

If you really want to inherit from std::array, you'll have to accept losing the aggregate status and provide any constructors you want yourself.


Note that the answer above applies to C++11 and C++14 only. In C++17, the definition of aggregates was loosened to allow public base classes in them, so simply deriving from std::array and removing the using declaration is enought to make the code compile:

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

std::array<float, 2> x = {1, 2};
vec2d z = {1, 2};

[Live example]


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...