0

This question consists of two parts, marked (A) through ...ahem... (C).

template< unsigned a > struct Outer {
    /*
(A)    Provide a match if the template parameter of Inner is the same
       as Outer.  Do something different in the general case (not shown)
    */
    template< unsigned b > struct Inner1;
    template<> struct Inner1<a> { enum { value = a }; };

    /*
(B)    Same idea as (A), but we want an additional template parameter
    */
    template< typename T, unsigned b > struct Inner2;
    template< typename T > struct Inner2< T, a > { enum { value = a }; };

    typedef Inner1<a> Result1;
    typedef Inner2<int, a> Result2;
};

// (C) Alternative way of defining our specializations?
template< unsigned a > template<> 
struct Outer<a>::template Inner1<a> {};

template< unsigned a > template< typename T >
struct Outer<a>::template Inner2<T, a> {};

void code() {
   Outer<1>::Result1::value; // OK, 
   Outer<1>::Result2::value; // error C2027: use of undefined type 'Outer<1>::Inner2<int,1>'
}

Using Visual Studio 2013 or 2015, without language extensions, (A) and (B) compile successfully. (C) helpfully fails with fatal error C1001: An internal error has occurred in the compiler.

(A) Result1 is correctly selected to be the specialized template

(B) Result2 is not, resulting in the 'use of undefined type'.

I have read, though, that it is not OK to specialize a class template nested inside of a class template. Why has it worked here? If I want to provide this kind of behavior (matching on an outer template parameter) what better ways are there?

(C) I guess this is a case of "Don't do that..."

mkobierski
  • 59
  • 3

1 Answers1

0

Here is a way to accomplish case (B).

template< typename T, unsigned b, unsigned a > struct Inner;
template< typename T, unsigned a >
struct Inner< T, a, a > { enum { value = a }; };

template< unsigned a > struct Outer {
    typedef Inner<int, a, a> Result;
};

void code() {
    Outer<1>::Result::value; // OK, 
}

The only limitation is that Inner can no longer be in the private section of the original class (for example if it is an implementation detail of Outer an thus should have restricted access).

mkobierski
  • 59
  • 3