Использование независимого вложенного класса родительского класса шаблона в качестве члена дочернего класса

Я просматривал раздел шаблонов C++ в часто задаваемых вопросах по C++ и наткнулся на этот пример (кода который не компилируется) относительно использования независимых вложенных классов родительского шаблона class как члены дочернего класса:

template<typename T>
class B {
public:
  class Xyz { ... };  ← type nested in class B<T>
  typedef int Pqr;    ← type nested in class B<T>
};

template<typename T>
class D : public B<T> {
public:
  void g()
  {
    Xyz x;  ← bad (even though some compilers erroneously (temporarily?) accept it)
    Pqr y;  ← bad (even though some compilers erroneously (temporarily?) accept it)
  }
};

Часто задаваемые вопросы по С++ 35.18

К сожалению, это тоже не работает, потому что эти имена (вы готовы? вы садитесь?) не обязательно являются типами. "Хм?!?" ты говоришь. "Не типы?!?" — восклицаешь ты. "Это сумасшествие, любой дурак может ВИДЕТЬ, что они типы; только взгляните!!!" вы протестуете. Извините, дело в том, что они могут быть не типами. Причина в том, что может быть специализация B, скажем, B, где B::Xyz является членом данных, например. Из-за этой потенциальной специализации компилятор не может предположить, что B::Xyz является типом, пока не узнает T. Решение состоит в том, чтобы дать компилятору подсказку с помощью ключевого слова typename:

Итак, автор утверждает, что there can be a specialization of B<T>, say B<Foo>, where B<Foo>::Xyz is a data member, for example.. Это та часть, которую я действительно не понимаю - как можно было бы специализировать класс-шаблон (без наследования от него) добавить еще один член в класс, который в другой специализации (например, B<Baz>) не существовал бы ? Это, конечно, при условии, что такие вещи, как D static if, не существуют.

Я что-то упускаю?


person Andrei Bârsan    schedule 03.04.2013    source источник
comment
Тег C++-faq не имеет отношения к сайту.   -  person Luchian Grigore    schedule 03.04.2013


Ответы (1)


Когда вы явно специфицируете шаблон класса, вы полностью переопределяете класс для заданных аргументов шаблона. Вот простой пример:

template <typename T>
struct foo
{
  typedef T type;
};

template <>
struct foo<int>
{
  static int type;
};

Теперь, если я создаю экземпляр foo с любым другим аргументом шаблона, кроме int, член type является типом. В противном случае это элемент данных int.

person Joseph Mansfield    schedule 03.04.2013
comment
Здорово, я об этом не подумал! - person Andrei Bârsan; 03.04.2013