Что именно подразумевается под стандартом C ++ под «той же областью действия» в [basic.scope.hiding]? - PullRequest
3 голосов
/ 03 октября 2019

В стандарте C ++ 14, [basic.scope.hiding], пункт 2 (3.3.10.2), говорится:

Имя класса или имя перечисления может быть скрыто по именипеременная, член данных, функция или перечислитель, объявленные в той же области действия . Если имя класса или перечисления и переменная, член данных, функция или перечислитель объявлены в той же области действия (в любом порядке) с тем же именем, имя класса или перечисления будет скрыто везде, где переменная,Имя члена данных, функции или перечислителя является видимым.

Меня беспокоит формулировка "та же область действия". Действительно, в следующем фрагменте кода, в каких случаях класс C и переменная C объявляются в одной и той же области видимости?

namespace case_1 {
    int C;
    class C;
    // Here C refers to variable
}

namespace case_2 {
    class C;

    namespace nested {
        int C;
        // Here C refers to variable
    }
}

namespace case_3 {
    int C;

    namespace nested {
        class C;
        // Here C refers to class
    }
}

namespace case_4 {
    enum Enum { A, B, C };
    class C;
    // Here C refers to enumerator
}

Гипотеза 1: «одна и та же область действия» означает «тот же блок "

Если мы придерживаемся этой гипотезы, случай 1 должен касаться правила 3.3.10.2. Что насчет случая 2? Я полагаю, что оно охватывается правилом 3.3.10.1:

Имя может быть скрыто явным объявлением того же имени во вложенной декларативной области или производном классе.

Кроме того, эта гипотеза хорошо объясняет случай 3, где имя класса скрывает имя переменной (а не обратное), но не может объяснить случай 4. Действительно, перечислитель C объявлен в другом блоке, чем класс Cно класс все еще скрыт.

Гипотеза 2: «объявлено в той же области» означает «имеет точно такую ​​же область»

Если эта гипотеза верна, ни один случай, описанный в моем коде, не являетсяобеспокоен правилом, потому что невозможно, чтобы два имени имели одинаковую область видимости. Даже переменная в case_1 имеет другую область видимости, чем класс. Действительно, область действия имени переменной начинается после ее объявления, то есть перед именем класса.

Гипотеза 3: «объявлено в той же области» означает «одно имя объявлено внутри области действия другого»

Если эта гипотеза верна, все описанные выше случаи должны быть охвачены правилом 3.3.10.2. Действительно, в case_1 и case_3 класс C объявлен в области действия переменной Ccase_2, C переменная объявлена ​​в области видимости C class;и в case_4 класс C объявлен в области действия перечислителя C. Однако case_3 не следует правилу, потому что именно эта переменная должна «победить» и оставаться видимой.


Как вы можете видеть, каждая из моих гипотез имеет недостаток, и я действительноне понимаю, что именно подразумевается под этим термином в этом абзаце.

Ответы [ 2 ]

3 голосов
/ 03 октября 2019

В каких случаях класс C и переменная C объявляются в одной и той же области видимости?

Варианты 1 и 4 имеют одинаковую область действия. Случаи 2 и 3 - это не одна и та же область применения.

Я действительно не могу найти точное определение в стандарте для «одного и того же» в этом контексте, но интерпретация, которая имеет смысл и соответствует результатам вашего теста, заключается всравните наименьшую охватывающую область действия (или, скорее, декларативную область 1 ) каждого объявления.

Гипотеза 1: "та же область действия" означает "один и тот же блок"

Хотя у блока есть область действия, они не эквивалентны. Есть также области имен и области классов, например.

, но не может объяснить случай 4. Действительно, перечислитель C объявлен в другом блоке, чем класс C, но класс все еще скрыт.

Объявления перечисления не имеют области видимости. Перечислитель и класс находятся в одной и той же области видимости.

Гипотеза 2: «объявлено в одной и той же области видимости» означает «имеют одинаковую область видимости»

Как вы говорите, ни одно объявление не может иметь точно такую ​​же область видимости с другим, поэтому такое толкование сделает правило бессмысленным.

Гипотеза 3: «объявлено в той же области» означает, что «одно имя объявлено внутриобласть действия другого "

Это неверная интерпретация, поскольку вложенная область действия может находиться в пределах одной декларации, но это не та же область, что касается рассматриваемого правила.


1 В последнем стандартном проекте формулировка была изменена для использования термина "декларативный регион", который, очевидно, имеет немного другое значение, чем "сфера применения". Это не меняет предполагаемого значения правила.

2 голосов
/ 03 октября 2019

Здесь под областью они понимают видимость. Два имени находятся в одной и той же области видимости, если и только если где-то они оба известны одновременно (так что становится неоднозначным / противоречивым, если они одинаковы). Под «известным» я имею в виду, что вы можете напрямую получить к ним доступ (с точно таким же синтаксисом, если имена совпадают).


Действительно, Cперечислитель объявлен в другом блоке, чем класс C , но класс все еще скрыт.

Это неправильно. На самом деле enum не инкапсулирует своих членов в локальной области видимости. Другими словами, элементы enum находятся в той же области, что и сама enum.

Например, если я объявлю

enum MY_ENUM {A, B};

, я могу получить доступ к значениям либо с помощью My_ENUM::A и My_ENUM::B или просто A и B. Более того, неявное преобразование в int разрешено.

Если вы хотите инкапсулировать значения в области видимости, локальной для MY_ENUM (и, таким образом, запретите доступ с помощью A и B), выВместо этого придется объявить enum как enum class.

enum class MY_ENUM {A, B};

Однако неявное преобразование в int больше не будет разрешено.

...