Search code examples
c++c++14multiple-inheritancepack-expansion

Multiple inheritance from a pack expansion


I recently saw this in production code and couldn't quite figure out what it does:

template <class... Ts>
struct pool : pool_type<Ts>... {
//...
};

I've never seen pack expansion happening for parent classes. Does it just inherit every type passed into the varargs?

The parents look like this:

template <class T>
struct pool_type : pool_type_impl<T> {
// ...
};

Solution

  • Does it just inherit every type passed into the varargs?

    Yes. It inherits publicly from each of the passed arguments. A simplified version is given below.

    From Parameter pack's documentation:

    Depending on where the expansion takes place, the resulting comma-separated list is a different kind of list: function parameter list, member initializer list, attribute list, etc. The following is the list of all allowed contexts:

    • Base specifiers and member initializer lists:
      A pack expansion may designate the list of base classes in a class declaration.

    Example

    struct Person 
    {
        Person() = default;
        Person(const Person&)
        {
            std::cout<<"copy constrcutor person called"<<std::endl;
        }
    };
    struct Name 
    {
        Name() = default;
        Name(const Name&)
        {
            std::cout<<"copy constructor Name called"<<std::endl;
        }
    };
    
    template<class... Mixins>
    //---------------vvvvvvvvv---------->used as list of base classes from which X inherits publicly
    class X : public Mixins...
    {
    public:
    //-------------------------------vvvvvvvvvvvvvvvvv---->used as member initializer list
        X(const Mixins&... mixins) : Mixins(mixins)... {}
    };
    int main()
    {
        Person p;
        Name n;
        X<Person, Name> x(p, n); //or even just X x(p, n);  works with C++17 due to CTAD
        return 0;
    }
    

    The output of the above program can be seen here:

    copy constrcutor person called
    copy constructor Name called
    constructor called
    

    Explanation

    In the above code, the X class template uses a pack expansion to take each of the supplied mixins and expand it into a public base class. In other words, we get a list of base classes from which X inherits publicly. Moreover, we also have a X constructor that copy-initializes each of the mixins from supplied constructor arguments.