Почему я не могу специализировать вложенный элемент шаблона, не специализируясь сначала на закрытии шаблона класса?

Вот код:

template <typename T>
struct A
   {
   template <typename U>
   struct B;
   };
template <typename T> template <> // 0_o
struct A<T>::B<int> {};

Я знаю, что не могу этого сделать, но мне больше интересно знать логически. Почему я не могу специализировать вложенный элемент шаблона, не специализируясь сначала на закрытии шаблона класса?

Я ценю любую помощь с логическим объяснением:)

Изменить:

Андрей Александреску ответил: "Нет особой причины - это просто языковое правило".

Ответы

Ответ 1

Вот идея, основанная на примере Xeo: во-первых, пусть наш первичный шаблон-кандидат:

template <typename T> struct Foo
{
    template <typename U> struct Bar { /* ... */ };
    /* ... */
};

Теперь предположим, что мы хотим специализировать внутренний шаблон гипотетически:

template <typename T> template <> struct Foo<T>::Bar<bool> { /* ... */ }
// not actual C++!

Но теперь предположим, что существуют специализации Foo:

template <> struct Foo<int>
{
    template <typename U> struct Bar { /* ... */ };
};
template <> struct Foo<char>
{
    template <typename U> U Bar() { }
};

Теперь, если вы хотите использовать Foo<S>::Bar<bool>? Когда S = char, мы не можем использовать внутреннюю специализацию, потому что это не имеет никакого смысла. Но если мы откажемся от внутренней специализации для всех специализаций внешнего шаблона, то Foo<int>::Bar<bool> не специализируется, а Foo<float>::Bar<bool> будет специализированным. Поэтому наша гипотетическая внутренняя специализация не относится к Foo<int>, хотя можно было ожидать, что она должна.

Это не настоящая техническая причина, по которой это невозможно сделать, а просто иллюстрация, как это могло бы иметь очень неожиданное поведение. (Например, представьте, что специализация для int была написана позже, а существующий код зависел от внутренней специализации.)