1

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?

CodeBricks
  • 1,771
  • 3
  • 17
  • 37

2 Answers2

3

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>> { ... };
Community
  • 1
  • 1
David G
  • 94,763
  • 41
  • 167
  • 253
  • 1
    Would you please give a complete working example? I followed your suggestion [here](http://coliru.stacked-crooked.com/a/af96ed244245f656), and either I'm misinterpreting it or it doesn't compile. I included another alternative commented out, which also doesn't compile. – CodeBricks May 25 '14 at 23:36
  • +1, that's what I wanted to have explained in the first place. – Marco A. May 25 '14 at 23:37
  • 1
    @CodeBricks Your primary template is incorrect. `Foo` is a type, so the second parameter in the primary template should be also. [See here.](http://coliru.stacked-crooked.com/a/833ee6f2e2cb28c8) – David G May 25 '14 at 23:38
  • @0x499602D2 Your solution compiles! Am I correct in concluding that your main template’s type parameter `E` is specialized to two parameters: `template class Foo` and `typename E`? – CodeBricks May 25 '14 at 23:48
  • 1
    @CodeBricks No. The name for the template parameter `E` is an arbitrary name. In fact, since the name isn't being used anywhere in the primary template, it can be removed resulting in `template class Bar;`. The only specialization that is occurring is in the second template, where again the template names have nothing to do with the primary template definition of `Bar`. The only thing that matters is how the types are being configured in the specialization. – David G May 25 '14 at 23:52
  • Hm, as it stands, this question doesn't answer the OP's question. Could you edit it to contain all the relevant discussion so that it stands on its own? – Kerrek SB May 26 '14 at 00:08
  • The name of a of a type within template template parameter can't actually be used. -> It can be used in some situations. – Constructor May 26 '14 at 05:56
  • @Constructor What situations exactly?? – David G May 26 '14 at 13:08
  • @Constructor Ooo, that's nice! I guess I should have said *outside* the template. :) – David G May 26 '14 at 13:12
  • Yes, I think just like you. :-) – Constructor May 26 '14 at 13:17
1

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.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084