Ответ 1
Следующее:
enum class E : CL<E>::UndType;
Не принимается как допустимое объявление в некоторых текущих реализациях (проверены clang++, g++ и MSVC). Они не принимают неполный тип E
в базе enum CL<E>::UndType
. Ошибка, указанная в проверенных реализациях, заключается в том, что E
не указывается в этой точке. Кажется, что они помещают точку объявления в конце базы enum, они считают ее объявленной после ее завершения.
При чтении спецификаций
§14.3.1/2 Аргументы типа шаблона
[Примечание. Аргумент типа шаблона может быть неполным (3.9). - конечная нота]
И
§7.2/6 Объявления перечисления
Перечисление, базовый тип которого является фиксированным, является неполным типом из его точки объявления (3.3.2) сразу после его enum-base (если таковой имеется), после чего он становится полным.
Подчеркивает, что он компилируется; как в случае реализации CRTP.
Я уверен, что если это (т.е. неспособность скомпилировать enum class E : CL<E>::UndType;
) является намерением или если оно считается прецедентом. Из спецификации в непрозрачной декларации перечисления дается некоторое "специальное" обращение w.r.t. его базовый тип и требование, чтобы он был интегральным типом.
Предположительно, код должен быть скомпилирован с учетом CWG # 1482.
Что касается текущих обходных решений...
Это
enum class E; // default underlying type is int
Является минимальным объявлением.
Прозрачная декларация может быть:
enum class E : int; // int base
Следующее будет полным определением (включая счетчики);
enum class E : int {/*...*/};
Или для использования шаблона класса можно использовать другой тип (возможно, void
).
enum class E : CL<void>::UndType;