Reserved names in the global namespace
Asked Answered
T

3

5

Arising from my answer to Dynamic array of objects in C++ and as a follow up to What are the rules about using an underscore in a C++ identifier?: apparently, names beginning with _ followed by an uppercase letter are reserved in the global namespace.

17.4.3.2.1 Global names [lib.global.names]

Certain sets of names and function signatures are always reserved to the implementation:

  • Each name that contains a double underscore (__) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.
  • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.165

165) Such names are also reserved in namespace ::std (17.4.3.1).

In my answer to the first question I had a class that looked like this

class A
{
 private:
   vector<int> _Ints;
}

In the comments I was told the _Ints identifier invokes undefined behavior, since it is a reserved name. However, according to the recent draft of the standard, name look-up of a member variable occurs using the following rule:

3.4.3.1 Class members [class.qual]

If the nested-name-specifier of a qualified-id nominates a class, the name specified after the nested-namespecifier is looked up in the scope of the class (10.2), except for the cases listed below. The name shall represent one or more members of that class or of one of its base classes

To me, that means that no member variable can ever be part of the global namespace, as its scope is the class.

And now, the question:

Is my understanding correct that member variables will never violate the implementation reserved names rule since they are not in the global namespace? If I am not correct, could someone explain my misunderstanding of the look-up rule?

Twelfth answered 12/3, 2012 at 14:27 Comment(0)
H
6

_Int clearly violates the first rule: “Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.” “any use” means exactly what it says: it could be a predefined macro, or trigger some special behavior in the compiler, or anything else the compiler author wants. It doesn't matter where you use the name, if you use it, it's undefined behavior (unless the compiler documentation states otherwise).

More generally, historically at least, compilers have been rather lax, and a number of system headers have traditionally included macros with names starting with a single underscore followed by a lower case letter. It's probably best avoiding those as well. (Historically, even, there have been names without an underscore as well. I know I've had problems with the name linux becoming 1. No underscores in sight, but... There's not much you can do about this, however, except change the name when the conflict occurs.)

Even more generally, underscores don't show up that well in some fonts, and it's best avoiding them at either end of a symbol.

Hylozoism answered 12/3, 2012 at 14:38 Comment(4)
"underscores don't show up that well in some fonts" - 1, l and I look similar in some fonts, so avoid those in identifiers? Or avoid those fonts when reading code?Clavichord
I agree with Steve, underscores are a fact of life in programming, if your font can't render them then you have problems. (I use proportional fonts and still don't have problems)Sasin
I am fairly extreme on this though - if I can avoid it I don't read code in a "font" (or anyway text editor setting) that doesn't distinguish between a tab character and an equivalent number of spaces. So I have quite high standards of basic text readability.Clavichord
@SteveJessop Having symbols which differ only because one uses small letter l and the other uses number 1 isn't a good idea. As for underscores, they separate words (where the fact that they resemble a space isn't too great of a problem), but distinguishing between _name, name_ and name is barely better than using x1, xl or xO and x0.Hylozoism
H
3

The rules you quoted from the standard state that an identifier starting with an underscore followed by an uppercase letter is reserved for any use, not just in the global namespace. So naming a member variable _Ints is not allowed.

Identifiers starting with an underscore which is not followed by an underscore or uppercase letter are reserved in the global namespace. So you are allowed to name a member variable _ints for example, but you can't have a global variable named _ints which is in the global namespace.

Hanschen answered 12/3, 2012 at 14:37 Comment(2)
I took use to mean "Any purpose" not any scope. why is that rule under the global names section.Twelfth
@Twelfth Surely "any purpose" includes declaring a variable in any scope. The section name is confusing, but what's important is the text of the section, and that clearly separates reserved identifiers into two types: those reserved for any use, and those reserved in the global namespace.Hanschen
S
1

apparently _(Upercase Letter) is reserved in the global namespace.

No. It is reserved everywhere. Read 17.4.3.2.1 again:

Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.

This doesn’t mention “global namespace” at all (the global namespace is only relevant in the subsequent rule).

Scheider answered 12/3, 2012 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.