5

I'm having trouble specializing an inner template when it's parameters are all known. Here's an example:

template < typename T0 >
struct outer
{
    template < typename T1 = void, typename T2 = void >
    struct inner
    {
        typedef T1 type;
    };
};
template < typename T0 >
template < typename T1 >
struct outer<T0>::inner<double,T1> { typedef int type; };

This works just fine. If I instead specify the inner template like so, it does not:

template < typename T0 >
template < >
struct outer<T0>::inner<double,void> { typedef int type; };

For this I get the error message, "invalid explicit specialization before ‘>’ token...enclosing class templates are not explicitly specialized...template parameters not used in partial specialization:...T0". Not sure WTAF is going on here.

I also tried this:

template < typename T0 >
struct outer<T0>::inner<double,void> { typedef int type; };

I expected this to fail and the error message is not surprising. It was: "too few template-parameter-lists".

So, what's the correct way to do this? I can of course hack around it, but if I don't have to I'd prefer not.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • related: http://stackoverflow.com/questions/9219157/why-cant-i-specialize-the-nested-template-member-without-specializing-enclosing?lq=1 – Nate Kohl Jun 16 '13 at 02:20
  • Hmm...I did do a search but that didn't show up. Must have not sacrificed the correct species of goat before doing so. – Edward Strange Jun 16 '13 at 02:22

1 Answers1

7

That is not allowed. You cannot fully specialize a member of a class template that has not been itself fully specialized.

Per paragraph 14.7.16 of the C++11 Standard:

In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. [...]

Also, paragraph 14.7.3/15 of the C++11 Standard says:

A member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized. [ Example:

template<class T1> class A {
     template<class T2> class B {
         void mf();
     };
};
template<> template<> class A<int>::B<double>;
template<> template<> void A<char>::B<char>::mf();

end example ]

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • It's not a member function, but I suppose the same rule applies to nested types? – Nate Kohl Jun 16 '13 at 02:11
  • Assuming Nate is correct. Can you cite chapter/verse? 03 is better, but 11 would do. – Edward Strange Jun 16 '13 at 02:12
  • 1
    @CrazyEddie: Yes, I'm looking for a quote – Andy Prowl Jun 16 '13 at 02:13
  • @CrazyEddie: I added the reference to the standard – Andy Prowl Jun 16 '13 at 02:16
  • Maybe 14.7.3/16 is more appropriate? ("...except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.") – Nate Kohl Jun 16 '13 at 02:17
  • Not sure about 11, but 03 has 14.7.3/18 and in it there's explicitly stated that what I'm attempting is ill-formed. Also states, "...except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well." Cool though, answer accepted. – Edward Strange Jun 16 '13 at 02:21
  • @NateKohl: Yes, correct. I was just about to add that, thank you for mentioning it! – Andy Prowl Jun 16 '13 at 02:22
  • @Andy - well, it means my hack is necessary instead of just a misunderstanding on my part :P Thanks. – Edward Strange Jun 16 '13 at 02:24