Зависимые параметры шаблона, не относящиеся к типу

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

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> {/* ... */};
};

Схема класса выше компилируется и функционирует должным образом при тестировании на VC++ 2010 и Comeau C++. Однако, когда Foo превращается в сам шаблон, приведенный выше фрагмент не работает в VC++ 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

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

person rybz    schedule 18.07.2010    source источник
comment
Я бы сказал, что сообщения об ошибках являются поддельными. FWIW, Комо принимает код, даже если Foo является шаблоном. Я предлагаю вам попробовать в одной из групп новостей MS. Люди, занимающиеся компиляцией MS, тусовались там.   -  person sbi    schedule 18.07.2010


Ответы (1)


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

Вы можете сделать тип перечисления независимым, объявив его в базовом классе, не являющемся шаблоном (C++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 будет каким-то образом зависимым, это не сделает его неправильно сформированным, если оно не зависит от параметра специализации, как в примере вашей ссылки «класс ошибки».

person Johannes Schaub - litb    schedule 18.07.2010
comment
Довольно раздражает, что Microsoft не может создать соответствующий компилятор, учитывая всю их рабочую силу. Особенно, если принять во внимание запрашиваемую цену за платные версии. - person rybz; 19.07.2010
comment
@litb: я не уверен, что понимаю: как Flags зависит от параметра специализации? - person HighCommander4; 28.04.2012