Правило для:: оператора в С++

Я думаю, что оператор :: может быть унарным в случае доступа к глобальной области. Во всех остальных случаях :: рассматривается как двоичный оператор, а правило оценки для оператора :: в случае N1::N2::N3::n эквивалентно следующему:

((N1::N2)::N3)::n // Error: ::n has not been declared

Но эта строка не компилируется. Это очень любопытно. В стандарте нет информации об оценке nested-name-specifier. Было бы естественно, если оценка nested-name-specified эквивалентна qualified/unqualified-id, , но она не говорит об этом нигде в стандарте.. Можно ли предположить, что оценка a nested-name-specifier зависит?

Ответ 1

Оператор разрешения области :: является право-ассоциативным, поскольку рекурсивная грамматика производной вложенного имени-спецификатора является право-ассоциативной:

nested-name-specifier:
    ::[opt] type-name ::
    ::[opt] namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier template[opt] simple-template-id ::

Соответствующее правило для рекурсивной оценки вложенного имени-спецификатора тогда будет 3.4.3 [basic.lookup.qual]:

1 - Название члена класса или пространства имен или перечислителя можно передать после оператора разрешения области видимости :: (5.1), примененного к спецификатору вложенных имен, который обозначает его класс, пространство имен или перечисление. [...]

Важно отметить, что в отличие от 5.1, в котором обсуждается поиск только квалифицированных идентификаторов (в 5.1.1p8), 3.4.3p1 неограничен и поэтому может быть использован для рекурсивного поиска вложенных имен-спецификаций.

То есть в:

namespace A {
    namespace B {
        struct C {
            struct D {
                static int i;
            };
        };
    }
}
A::B::C::D::i;

A::B::C::D::i анализируется как квалифицированный идентификатор, содержащий рекурсивно вложенные имена-спецификаторы A::B::C::D::, A::B::C::, A::B:: и A::. Теперь, чтобы оценить A::B::C::D::i:

  • мы используем 5.1.1p8, что требует оценки A::B::C::D;
  • мы используем 3.4.3p1, что требует оценки A::B::C;
  • мы используем 3.4.3p1, что требует оценки A::B;
  • мы используем 3.4.3p1, что требует оценки A.

Теперь нам нужно найти смысл, в котором A "обозначает" класс, пространство имен или перечисление ". В отсутствие чего-то более конкретного, раздел 3 относится к 3.4:

1 - Правила поиска имен применяются равномерно ко всем именам (включая typedef-names (7.1.3), namespace-names (7.3) и имена классов (9.1)), где грамматика допускает такие имена в обсуждаемом контексте по определенному правилу. [...]

Поиск A теперь выполняется в соответствии с правилами 3.4.1 [basic.lookup.unqual] применительно к конкретному контексту. Поскольку мы находимся в глобальной области действия, применяется 3.4.1p4 и мы ищем глобальную область для имени A. Мы находим пространство имен A, и оценка A::B::C::D::i продолжается соответственно.


То есть, самое левое (внутреннее) имя в вложенном имени-спецификаторе рассматривается как неквалифицированное имя; последовательные имена рассматриваются как квалифицированные имена в их внутреннем вложенном имени-спецификаторе.

Ответ 2

В [expr.prim.general] (5.1.1/8-9) перечислены правила синтаксического анализа ::. Он требует, чтобы за :: следовало имя пространства имен/класса или имени члена пространства имен/класса. ( и ) не разрешены.

Более конкретно в [over.oper] (13.5/1) стандарт определяет operator-function-id и operator как один из new, delete, +, -, !, =, ˆ=, &=, <=, >=, (), [], new[], *, <, |=, &&, delete[], /, >, <<, ||, %, +=, >>, ++, ˆ, -=, >>=, --, &, *=, <<=, ,, |, /=, ==, ->*, , %=, !=, ->.

., .*, ::, ?: названы как исключение в разделе 9, чтобы не действовать как обычные унарные или двоичные операторы.

Ответ 3

Ничего не зависит от реализации. Вы ошибочно полагаете, что это оператор. Не это. Поэтому он не является ни унарным, ни двоичным оператором, и он не формирует выражения. И поскольку он не формирует выражений, нет оценки этих выражений.