1
votes

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?

2

2 Answers

3
votes

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>> { ... };
1
votes

Like this:

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

You can even omit the inner parameter name E, since it serves no purpose.