Name lookup Clarification
Asked Answered
L

2

2

$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?

Lucania answered 4/11, 2010 at 6:1 Comment(3)
Ouch. The compiler should have stopped at about line 3 and told you to refactor your code.Evslin
@Greg Hewgill: oh vow!. Compilers and refactoring. Innovation at it's best!Lucania
>>is it yet another day for me to stay away from C++ Standard document? - yes.Mulloy
M
2

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...

Mercie answered 4/11, 2010 at 6:43 Comment(0)
C
0

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.

Charinile answered 15/8, 2011 at 15:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.