Search code examples
c++templatespartial-specializationtemplate-templates

Partial specialization of type parameter in template class with type & template template parameters


I want to specialize the type parameter of the following template class, which has a type parameter and a template template parameter:

template <
    typename T,
    template <typename E> class Foo
> class Bar;

I tried every permutation of adding and/or omitting .template and typename in the last line of each of the following snippets, and none compiles:

1.)

template <
    template <typename E> class Foo
> class Bar<int, Foo<typename E>>;

2.)

template <
    template <typename E> class Foo
> class Bar<int, Foo.template <typename E>>;

3.)

template <
    template <typename E> class Foo
> class Bar<int, Foo<E>>;

4.)

template <
    template <typename E> class Foo
class Bar<int, Foo.template <E>>;

Why doesn't any of them work?

Regarding the last line of each applicable snippet:

  • Doesn't typename clarify E is a type used by class Foo, or can this syntax only be used within the {} body of Bar's class definition?
  • Doesn't template clarify Foo is a template and therefore prevent the compiler from parsing Foo < as Foo "is less than", or can this syntax only be used within the {} body of Bar's class definition?

How can I get this to work?


Solution

  • Doesn't typename clarify E is a type used by class Foo, or can this syntax only be used within the {} body of Bar's class definition?

    typename is only used when you are defining a type within a template definition (class could also be used) or when you are accessing a dependent type (a type that depends on a template parameter).

    For more information (even about when template is used) see this thread.

    How can I get this to work?

    The name of a of a type within template template parameter can't actually be used. It's just there as a formality. You have to add another template parameter to your main template instead:

    template <
        template<typename> class Foo,
        typename E
    > class Bar<int, Foo<E>> { ... };
    

    Moreover, if this is a specialization of the template Bar, then Bar needs a primary template to specialize:

    template<typename T, typename U>
    struct Bar;
    
    template <
        template<typename> class Foo,
        typename E
    > class Bar<int, Foo<E>> { ... };