user2953119
user2953119

Reputation:

rule for :: operator in c++

I think that the :: operator can be unary in the case of accessing the global scope. In all other cases :: is treated as a binary operator, and the evaluation rule for the :: operator in the case of N1::N2::N3::n is equivalent to the following:

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

But that line doesn't compile. It is very curious. There is not any information in the standard about the evaluation of nested-name-specifier. It would be natural if the evaluation of nested-name-specified is equivalent to qualified/unqualified-id, but it does not say this anywhere in the standard. So can we assume that evaluation of a nested-name-specifier is implementation-dependent?

Upvotes: 11

Views: 539

Answers (3)

Danvil
Danvil

Reputation: 23031

In [expr.prim.general] (5.1.1/8-9) the parsing rules of :: are listed. It requires that :: is followed by the name of a namespace/class or the name of a member of a namespace/class. ( and ) are not allowed.

More specifically in [over.oper] (13.5/1) the standard defines operator-function-id and operator as one of new, delete, +, -, !, =, ˆ=, &=, <=, >=, (), [], new[], *, <, |=, &&, delete[], /, >, <<, ||, %, +=, >>, ++, ˆ, -=, >>=, --, &, *=, <<=, ,, |, /=, ==, ->*, , %=, !=, ->.

., .*, ::, ?: are named as an exception in clause 9 to not act as ordinary unary or binary operators.

Upvotes: 9

ecatmur
ecatmur

Reputation: 157414

The scope resolution operator :: is right-associative because the recursive grammar of the nested-name-specifier production is right-associative:

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

The appropriate rule for recursively evaluating a nested-name-specifier is then 3.4.3 [basic.lookup.qual]:

1 - The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. [...]

Importantly, unlike 5.1, which only discusses lookup of qualified-ids (in 5.1.1p8), 3.4.3p1 is unrestricted and so can be used to lookup nested-name-specifiers recursively.

That is, in:

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

A::B::C::D::i is parsed as a qualified-id containing recursively the nested-name-specifiers A::B::C::D::, A::B::C::, A::B::, and A::. Now, to evaluate A::B::C::D::i:

  • we use 5.1.1p8, which requires evaluation of A::B::C::D;
  • we use 3.4.3p1, which requires evaluation of A::B::C;
  • we use 3.4.3p1, which requires evaluation of A::B;
  • we use 3.4.3p1, which requires evaluation of A.

Now we have to find a sense in which A "denotes" a "class, namespace or enumeration". In the absence of anything more specific, section 3 refers us to 3.4:

1 - The name lookup rules apply uniformly to all names (including typedef-names (7.1.3), namespace-names (7.3), and class-names (9.1)) wherever the grammar allows such names in the context discussed by a particular rule. [...]

The lookup of A now proceeds according to the rules of 3.4.1 [basic.lookup.unqual] as applied to the particular context. Since we are in global scope, 3.4.1p4 applies and we search global scope for name A. We find the namespace A, and evaluation of A::B::C::D::i proceeds accordingly.


That is, the leftmost (innermost) name in a nested-name-specifier is looked up as an unqualified name; successive names are looked up as qualified names on their inner nested-name-specifier.

Upvotes: 8

MSalters
MSalters

Reputation: 179991

There's nothing implementation dependent. You are incorrectly assuming it's an operator, though. It's not. Therefore, it's neither a unary nor a binary operator, and it does not form expressions. And since it doesn't form expressions, there's no evaluation of those expressions.

Upvotes: 1

Related Questions