c++templatesstltemplate-templates

c++ - passing standard container as a template template parameter


So, I need to make a mixin class that would encapsulate children of some derived class. The derived class should inherit from the mixin while providing a container template as a template template argument for the mixin.

The desired code is somewhat like that:

/*template definition*/
template<template<typename T, typename A> class C>
class HasChildren {
  protected:
    C<T, A> m_children;
    /* whatever */
};
 

It has an array of issues:

  1. When trying to instantiate this class like HasChildren<std::vector<int>>(just for testing), compiler says expected a class template, got ‘std::vector<int>’. Clearly, I'm not passing a template template. I would like to know what exactly I'm trying to pass.
  2. For C<T, A> m_children; compiler says that T and A are out of scope. When I add typename keyword for them, the error changes to error: wrong number of template arguments (1, should be 2). I would like to know why T and A are out of scope and why adding typename leads to this error.

Solution

    1. You pass a type, std::vector<int>, instead of a template, std::vector.
    2. You need to accept the template template parameters too. template<typename T, typename A> does not make the template template use T and A. They are just for documentation and can be removed.

    Example:

    template <template <class, class> class C, class T, class A>
    //                                         ^^^^^^^  ^^^^^^^
    class HasChildren {
       protected:
        C<T, A> m_children;
    };
    
    int main() {
        HasChildren<std::vector, int, std::allocator<int>> hc;
    //              ^template^   ^-----parameters-------^
    }
    

    If you prefer to instantiate HasChildren like you originally tried, by using HasChildren<std::vector<int>>, you can do that by specializing HasChildren:

    template<class> class HasChildren; // primary
    
    // specialization:
    template<template <class, class> class C, class T, class A>
    class HasChildren<C<T,A>> {
       protected:
        C<T,A> m_children;
    };
    
    int main() {
        HasChildren<std::vector<int>> hc; 
    }