В С++ 14, в какой области объявлены незарегистрированные счетчики объявленных деклараций?
С++ 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
Ответы
Ответ 1
Перечисление E объявляется в пространстве имен N, хотя его определение задано в глобальном пространстве имен. Таким образом, доступ к нему возможен только в области N.
Затем функцию бара следует определять как:
int bar() {
return int(N::A);
//SAME AS --> return int(::N::A);
}