С++ 14 (точно, N4296) говорит относительно перечислений, в 7.2: 11:
Каждое имя перечисления и каждый неперечисленный счетчик объявляются в области который немедленно содержит спецификатор перечисления.
Теперь, что произойдет, если пространство имен N содержит непрозрачное enum-объявление перечисления E, а позже перечисление полностью объявлено из глобального пространства имен? Должны ли мы найти его перечисления в глобальном пространстве имен или в пространстве имен N?
Конечно, для того, чтобы непрозрачно объявить неперечисленное перечисление, он должен иметь фиксированный базовый тип. Рассмотрим следующий фрагмент кода.
namespace N { enum E : int; }
enum N::E : int {A,B};
namespace N {
int foo() {
return int(::N::B);
}
}
int bar() {
//return int(::A);
return int(A);
}
Первая строка в bar
закомментирована, потому что clang++ -std=c++14
говорит:
нет члена с именем 'A' в глобальном пространстве имен; вы имели в виду просто "А"?
Gcc не может скомпилировать обе строки в bar(). Таким образом, gcc и clang объявляют перечисления в пространстве имен N
.
Итак, мои вопросы:
- Какова область действия, которая непосредственно содержит спецификатор перечисления? (Я считаю, что это область глобального пространства имен).
- Если в глобальном пространстве имен должны быть определены счетчики
A
,B
? - В функции
bar
, почему::A
не ссылается на перечислитель, но простойA
делает? - Почему выражение
::N::B
в функцииN::foo
обозначает перечислитель?
EDIT 1: оригинальное объявление было enum ::N::E : int {A,B};
, но gcc не смог его разобрать (отчет об ошибке), поэтому я удалил ведущие двоеточия использовать enum N::E : int {A,B};
EDIT 2: поведение clang bug