Зависимые параметры шаблона без шаблонов

Рассмотрим следующий класс:

class Foo
{
  enum Flags {Bar, Baz, Bax};

  template<Flags, class = void> struct Internal;

  template<class unused> struct Internal<Bar, unused> {/* ... */};
  template<class unused> struct Internal<Baz, unused> {/* ... */};
  template<class unused> struct Internal<Bax, unused> {/* ... */};
};

Структура класса выше компилируется и функционирует как ожидалось при тестировании на VС++ 2010 и Comeau С++. Однако, когда Foo превращается в сам шаблон, приведенный выше фрагмент разбивается на VС++ 2010.

Например, следующий фрагмент:

template<class> class Foo
{
  // Same contents as the original non-templated Foo.
};

Устанавливает следующий класс :

C2754: 'Foo<<unnamed-symbol>>::Internal<Bar,unused>' : a partial specialization cannot have a dependent non-type template parameter
C2754: 'Foo<<unnamed-symbol>>::Internal<Baz,unused>' : a partial specialization cannot have a dependent non-type template parameter
C2754: 'Foo<<unnamed-symbol>>::Internal<Bax,unused>' : a partial specialization cannot have a dependent non-type template parameter

  • Кто-нибудь может объяснить, что здесь происходит на простом английском языке?
  • Как я могу исправить это (т.е. сохранить внутренние псевдо-явные специализации в шаблоном Foo) на VС++ 2010?

Ответ 1

Как я могу исправить это (т.е. сохранить внутренние псевдо-явные специализации в шаблоном Foo) на VС++ 2010?

Вы можете сделать тип перечисления независящим, объявив его в базовом классе, отличном от шаблона (С++ 03 сделал вложенные классы зависимыми в #108, но это не включает перечисление, но даже если такой код все равно будет законным).

struct FooBase { 
  enum Flags {Bar, Baz, Bax};
};

template<class> class Foo : public FooBase {
  template< ::FooBase::Flags, class = void > struct Internal;
  // same other stuff ...
};

Ссылка "класс ошибки" уже дает описание предполагаемых случаев, когда ошибка должна быть повышена. Ошибка считает, что все зависимые типы запрещены, но на самом деле это то, что говорит стандарт:

Тип параметра шаблона, соответствующего специализированному аргументу не-типа, не зависит от параметра специализации.

Таким образом, даже если имя Flags будет каким-то образом зависеть, это не сделает его плохо сформированным, если оно не зависит от параметра специализации, например, в примере вашей ссылки "класс ошибки",