Search code examples
c++c++11initializationinitializer-list

Initializing object of derived class using initializer-list


I got a struct B that is derived from a struct A.

struct A{
  int a;  
};

struct B : public A{
    int b;
};

Is there a straight way to initialize an object of type B without providing a constructor, let's say using initializer-list?

Some more insight:

I got two structs that I use to pass data between threads; the second one holds the same data as the first one, with the addition of some synchronization variable. I could make the first struct a data member of the second one, or just duplicate the declaration of data members in the second struct, to easily use the initializer-list; but I think that in this particular application it would be logically more correct that the second struct extends the first one.


Solution

  • There isn't an extremely concise solution, but there is a solution at least:

    #include <type_traits>
    #include <utility>
    
    struct B : A
    {
        int b;
    
        template <typename ...Args,
                  typename = typename std::enable_if<
                                 std::is_constructible<A, Args&&...>::value>
        B(int x, Args &&... args)
        : b(x), A(std::forward<Args>(args)...)
        { }
    };
    

    This solution isn't exactly short, but it is general. The new constructor for B exists only in those specializations which make sense, thanks to the enable-if SFINAE, so B is precisely as constructible as it can be.

    There is one more danger here that I didn't address, namely how explicit the new constructor should be. Ideally it should be as explicit as the matching A constructor, but that's a bit hard to detect programatically (as done in N4064 for pairs and tuples).