Специализация шаблона класса в классе?

Почему специализация S в legal и S в B не?

(если B не закомментирован) GCC 4.8.1: ошибка: явная специализация в области без пространства имен "класс B

#include <type_traits>
#include <iostream>

class Y {};
class X {};

struct A {
  template<class T, class = void>
  class S;

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };
};

/*
class B
{
    template<class T>
    class S;

    template<>
    class S < Y > {};

    template<>
    class S < X > {};
};
*/


int main()
{
    A::S< X > asd;
    std::cout << asd.i << std::endl;
}

на coliru: B прокомментировал

на coliru: с B (ошибка)

Ответ 1

Комментарии @jrok в значительной степени объясняют вашу ошибку компилятора. Вложенные классы в целом и вложенные шаблоны классов, в частности, представляют собой пыльный угол языка, который можно легко избежать (принимая во внимание совет Саттера Напишите то, что вы знаете и знаете, что пишете).

Просто создайте namespace detail, чтобы определить шаблоны классов SA и SB и их специализации, а затем определите псевдоним типа вложенного шаблона S внутри A и B

namespace detail {

  template<class T, class = void>
  class SA;

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };

  template<class T>
  class SB;

  template<>
  class SB < Y > {};

  template<>
  class SB < X > {};
}

struct A
{
    template<class T>
    using S = detail::SA<T>;
};

struct B
{
    template<class T>
    using S = detail::SB<T>;
};

Конечно, для этого случая это может показаться излишним, но если вы когда-либо захотите сделать шаблоны классов A и B сами, а specialize A и B, то вы можете специализировать только вложенные шаблоны классов если вы также специализируетесь на включении класса. Короче говоря, просто избегайте этих проблем в целом дополнительным уровнем косвенного времени.