Question

$10.2/4- "[ Note: Looking up a name in an elaborated-type-specifier (3.4.4) or base-specifier (Clause 10), for instance, ignores all nontype declarations, while looking up a name in a nested-name-specifier (3.4.3) ignores function, variable, and enumerator declarations."

I have found this statement to be very confusing in this section while describing about name lookup.

void S(){}

struct S{
   S(){cout << 1;}
   void f(){}
   static const int x = 0;
}; 

int main(){ 
   struct S *p = new struct ::S;  // here ::S refers to type
   p->::S::f();

   S::x;  // base specifier, ignores the function declaration 'S'

   ::S(); // nested name specifier, ignores the struct declaration 'S'.
   delete p;
} 

My questions:

  1. Is my understanding of the rules correct?

  2. Why ::S on the line doing new treated automatically to mean struct S, whereas in the last line ::S means the functions S in the global namespace.

  3. Does this point to an ambiguity in the documentation, or is it yet another day for me to stay away from C++ Standard document?

Was it helpful?

Solution

Q1: I think so.

Q2: Compatibility with C. When you declare a struct in C, the tag name is just that, a tag name. To be able to use it in a standalone way, you need a typedef. In C++ you don't need the typedef, that makes live easier. But C++ rules have been complicated by the need to be able to import already existing C headers which "overloaded" the tag name with a function name. The canonical example of that is the Unix stat() function which uses a struct stat* as argument.

Q3: Standard reading is usually quite difficult... you need to already know that there is no place elsewhere modifying what you are reading. It isn't strange that people knowing how to do that are language lawyer...

OTHER TIPS

You are mistaken about the second comment. In S::x, the S is a name in a nested name specifier. What the Standard refers to with "base-specifier" is the following

namespace B { struct X { }; void X() }
struct A : B::X { }; // B::X is a base-specifier

You are also not correct about this:

::S(); // nested name specifier, ignores the struct declaration 'S'.`

That code calls the function not because ::S would be a nested-name-specifier (it isn't a nested-name-specifier!), but because function names hide class or enumeration names if both the function and the class/enumeration are declared in the same scope.

FWIW, the following code would be equally valid for line 2 of your main

p->S::f();

What's important is that S preceedes a ::, which makes lookup ignore the function. That you put :: before S has no effect in your case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top