What name spaces are there and what are the rules? - c++

Note: this question is about name space, not namespace.
The C++ standard has some references to name space, but I don't see the definition of this. The standards says that labels and macros are in different name spaces. All the other references to name space are in the C/C++ compatibility section, like this (current draft):
This is one of the few incompatibilities between C and C++ that can be attributed to the new C++ name space definition where a name can be declared as a type and as a non-type in a single scope causing the non-type name to hide the type name and requiring that the keywords class, struct, union or enum be used to refer to the type name. This new name space definition provides important notational conveniences to C++ programmers and helps making the use of the user-defined types as similar as possible to the use of fundamental types.
What is this new name space definition? Where can I find it in the standard? What are the exact rules? The rules seem to be more complicated, than "non-types hide types". Like, this doesn't compile:
typedef int Foo; // Foo is a type
void Foo(); // not a type, but compile error, instead of hiding
But this does:
struct Foo { }; // Foo is a type as well
void Foo(); // This hides the type Foo. "struct Foo" refers to the type
And this doesn't compile either:
struct Foo { }; // Type
namespace Foo { } // Non-type, but compiler error instead of hiding

The name space term may be more well-established in the ISO C Standard; citing ISO C11:
6.2.3 Name spaces of identifiers
If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:
label names (disambiguated by the syntax of the label declaration and use);
the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct, union, or enum);
the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the . or -> operator);
all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).
The new name space definition of C++ is, however, not in any way recent in time, and has been described in [diff.class]/1 in its current form ever since the ISO C++ Standard's introduction in '98. It's only ever mentioned in any length in the contexts for which it differs from ISO C, as per [diff.class]/1 which is quoted by the OP.
Afaics we need to resort to ISO C11/6.2.3 and combine it with [diff.class]/1 of the ISO C++ Standard for a cohesive and complete description of the (new) name space definition of C++, less we scourge the ISO C++ Standard for e.g. [basic.scope.hiding], [class.name]/2, [stmt.label]/1, [cpp.replace]/8 and so on to see how and where it applies.
[class.name]/2
A class declaration introduces the class name into the scope where it is declared and hides any class, variable, function, or other declaration of that name in an enclosing scope. [...]
[stmt.label]/1
[...] Labels have their own name space and do not interfere with other identifiers [...]
[cpp.replace]/1
[...] There is one name space for macro names. [...]

In C (6.2.3 Name spaces of identifiers) the notion of name spaces is defined the following way.
1 If more than one declaration of a particular identifier is visible
at any point in a translation unit, the syntactic context
disambiguates uses that refer to different entities. Thus, there are
separate name spaces for various categories of identifiers, as
follows:
— label names (disambiguated by the syntax of the label declaration
and use);
— the tags of structures, unions, and enumerations (disambiguated by
following any32) of the keywords struct, union, or enum);
— the members of structures or unions; each structure or union has a
separate name space for its members (disambiguated by the type of the
expression used to access the member via the . or -> operator);
— all other identifiers, called ordinary identifiers (declared in
ordinary declarators or as enumeration constants).
So for example a structure tag name can coincide with a function name because they belong to different name spaces. When you specify a structure with a structure tag name when you have to use the keyword struct. So for example these declarations do not conflict.
struct s
{
int s;
};
void s( void );
struct s s1;
In this code snippet the tag name s of the structure does not conflict with the function name s because the tag name shall be specified with the keyword struct.
In C++ you are allowed to use structure tag names without the keyword struct.
For example
struct s
{
int s;
};
s s;
is a correct code. In this declaration
s s;
the name of the declared identifier s hides the structure name. SO if then you will write for example
s s1;
then the compiler will issue an error because in this statement s is considered as the name of the identifier declared above. To resolve the ambiguity you need to use the keyword struct
struct s
{
int s;
};
s s;
struct s s1;
This is described in the following quote from the C++ 20 Standard (6.3.1 Declarative regions and scopes)
4 Given a set of declarations in a single declarative region, each of
which specifies the same unqualified name,
(4.1) — they shall all refer to the same entity, or all refer to
functions and function templates; or
(4.2) — exactly one declaration shall declare a class name or
enumeration name that is not a typedef name and the other declarations
shall all refer to the same variable, non-static data member, or
enumerator, or all refer to functions and function templates; in this
case the class name or enumeration name is hidden (6.3.10). [ Note: A
namespace name or a class template name must be unique in its
declarative region (10.3.2, Clause 17). — end note ]
As you can see from the quote a namespace name must be unique in its declarative region. So these declarations
struct Foo { };
namespace Foo { }
are incorrect.

Related

Parameter type lookup for out-of-namespace function definitions

The software project I lead occasionally uses nested namespaces as a means of indicating which parts of the library are intended to be internal and should not be considered user-facing. For example:
namespace project::detail {
// Hands off; library implementation internals
class Internal {};
int important_number(Internal internals);
}
Before C++17, the indentation would become somewhat dreadful (depending on the source code formatting), so we opted for defining functions out-of-namespace:
int
project::detail::important_number(Internal const internals)
{ ... }
Observe that although the type Internal was declared and defined in the project::detail nested namespace, it is not required to fully qualify the parameter type (i.e.):
int
project::detail::important_number(/*unnecessary*/ project::detail::Internal)
I have scoured en.cppreference.com and bits of the C++14 standard and have not found the place(s) that support the abbreviated function definition (the first example above). I am assuming the relevant rules did not change for C++17. Can anyone tell me which rules of the C++14/17 standard apply here--i.e. where does the standard support non-fully-qualified parameter types for out-of-namespace function definitions?
You're looking for unqualified name lookup and it can be found in the standard under basic.lookup.unqual
In the definition of a function that is a member of namespace N, a
name used after the function’s declarator-id shall be declared before
its use in the block in which it is used or in one of its enclosing
blocks or shall be declared before its use in namespace N or, if
N is a nested namespace, shall be declared before its use in one of
N’s enclosing namespaces.

Return alias identificator instead of type in typeid(SOME_TYPE).name()

In the following example
template <typename T>
void foo() {
const char* name = typeid(T).name();
std::cout << name;
}
the variable 'name' will be initialized by type 'T' name. It is very convinient if we need to print this template type name. But, if we have the alias:
using shortTypeName = std::smth::smth_else::smth_more;
in the result of the call
foo<shortTypeName>();
will be printed 'std::smth::smth_else::smth_more'. And I need to print exactly the alias name, but not the type it is defined. Can somebody give an advice, how I can do this?
... alias identificator ...
There's no such thing, at least not after compilation. It's just syntactic sugar and doesn't exist in any sense in the final executable.
The only way to grab the local name of a type (as opposed to the implementation-defined and probably-mangled typeid name) is with a stringize/stringify macro.
For future reference, this should eventually be possible when the Reflection TS lands - but I don't yet know whether to expect that to look like reflexpr(T).get_name(), or std::meta::name_of(^T), or something else again.
Can somebody give an advice, how I can do this?
The language does not support a mechanism to do this.
What you have is simply a type alias.
From http://en.cppreference.com/w/cpp/language/type_alias:
A type alias declaration introduces a name which can be used as a synonym for the type denoted by type-id. It does not introduce a new type and it cannot change the meaning of an existing type name.
You can't. Because a type alias is transparent: It is just a synonym for a new type, not a new type. As an implementation detail it doesn't even get mangled in the type system because it's not a type.
§7.1.3 The typedef specifier [dcl.typedef]
[...] A name declared with the typedef specifier becomes a typedef-name . Within the scope of its declaration, a typedef-name is
syntactically equivalent to a keyword and names the type associated
with the identifier in the way described in Clause 8. A typedef-name
is thus a synonym for another type. A typedef-name does not
introduce a new type the way a class declaration (9.1) or enum
declaration does.
A typedef-name can also be introduced by an alias-declaration . The identifier following the using keyword becomes a typedef-name and the
optional attribute-specifier-seq following the identifier appertains
to that typedef-name . It has the same semantics as if it were
introduced by the typedef specifier. In particular, it does not
define a new type and it shall not appear in the type-id .
typeid(T).name(); is pretty much useless anyway. Until we have proper introspection in C++ you have to resort to hacks to get what you want (macros, intrusive techniques or external code generator tools).

Template alias scope

As per http://en.cppreference.com/w/cpp/language/type_alias, aliases are block-level declarations. It doesn't say anything special about template aliases, so it should be read that template aliases are block-level declarations as well.
However, it is impossible to use template aliases at block level. The errors are different depending on the compiler - while g++ gives a meaningful message, saying that templates are not allowed at block scope, clang is completely cryptic. (example: http://coliru.stacked-crooked.com/a/0f0862dad6f3da61).
Questions I have so far:
Does cppreference fail to specify that template aliases can not be used at block scope? (Or do I need to take a reading course?)
Are the compilers correct in denying template aliases on block level (the feature I find very interesting for my particular coding habits)
If the answer to the second is Yes, what might be the rationale for this? Why would compiler deny me this pure syntax sugar?
An alias template is [temp.alias]
A template-declaration in which the declaration is an alias-declaration (Clause 7) declares the identifier to
be a alias template. An alias template is a name for a family of types. The name of the alias template is a
template-name.
And if we look at 14.2 [temp] we have
A template-declaration can appear only as a namespace scope or class scope declaration. In a function
template declaration, the last component of the declarator-id shall not be a template-id.
So yes cppreference is off saying that it can be declared at block scope and your compilers are correct. If you do click on the link of block declarations It will bring you to a list of declarations and in that it has Template declaration and in there it has
declaration of a class (including struct and union), a member class or member enumeration type, a function or member function, a static data member at namespace scope, a variable or static data member at class scope, (since C++14) or an alias template (since C++11) It may also define a template specialization.
As for why the standard says that templates can only be declared in namespace scope or class scope I like James Kanze answer
The problem is probably linked to the historical way templates were implemented: early implementation techniques (and some still used today) require all symbols in a template to have external linkage. (Instantiation is done by generating the equivalent code in a separate file.) And names defined inside a function never have linkage, and cannot be referred to outside of the scope in which they were defined.
The compilers are behaving correctly.
Section 14 of the C++14 standard:
A template-declaration can appear only as a namespace scope or class
scope declaration.

Why is it possible to declare a struct and a non-struct with the same name?

Apparently,
For reasons that reach into the prehistory of C, it is possible to declare a struct and a non-struct with the same name in the same scope. - (Bjarne Stroustrup - The C++ Programming Language. 4th Edition)
For example:
struct Ambig {};
// the struct must be referred to with the prefix struct
void Ambig(struct Ambig* buf) {}
I'm just curious what the initial reason was? Without understanding, it seems like an example of bad language design, that causes ambiguity and is confusing.
The reason, as stated in your quote from Stroustrup, is
historical. In C, you must always prefix the name of the
struct with struct; the name of the struct (like the name of
unions or enums) is called a tag, and lives in a completely
different name space than other symbols. So things like:
struct stat
{
// ...
};
int stat( char const* filename, struct stat* buf );
are perfectly legal. (The above is, in fact, part of Posix).
In C++, the name of a class (declared with class, struct or
union) or an enum is in the same namespace as everything else,
and unlike in C, you can write things like:
struct MyClass {};
MyClass variableName;
This would not be legal C. In C, the second line would have to be:
struct MyClass variableName;
The problem is that C++ needs to be able to use interfaces
defined in C (like the Posix interface, above). So C++ defines
some special rules to allow it: you can give a variable or
a function and a class type the same name. When you do, the
variable or function name has precedence, and hides the class
name, except in "elaborated type specifiers" (i.e. class,
struct, union or enum, followed by a symbol), where
non-type names are ignored in the lookup.
I'm just curious what the initial reason was? Without understanding, it seems like an example of bad language design, that causes ambiguity and is confusing.
In C it's a first implementation of name spaces. Identifiers live in different name spaces and the idea is they can have the same name if they are declared in different name spaces.
Name space for structure tags and ordinary identifiers are not the only two name spaces in C. There are four name spaces in C:
(C99, 6.2.3 Name spaces of identifiers p1) "Thus, there are separate name spaces for various categories of identifiers, as follows:
— label names (disambiguated by the syntax of the label declaration and use);
— the tags of structures, unions, and enumerations (disambiguated by following any24)
of the keywords struct, union, or enum);
— the members of structures or unions; each structure or union has a separate name
space for its members (disambiguated by the type of the expression used to access the
member via the . or -> operator);
— all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants)."
The reason it is like this has to do with C++ inheriting from C. It was not "added" to C++, it is there because it works that way in C.
In C, you have to use struct X and union Y (there is no class keyword in C), or use typedef struct X A; and then use the name A instead of strcut X (where X and A could be the same name).
In C++ the compiler will, as long as the name is unique, understand that X is referring to struct X. You don't have to type struct, union or class in front of the name, or use typedef to create a new, standalone name.
Since C++ is designed to allow (wherever possible) the use of C syntax, it is still allowed to write struct X when referring to a struct. This allows the use of a name that is otherwise ambiguous.
It is highly recommended to NOT make use of this "possibility" unless required by historical design decisions, because all it will achieve is more confusion...
Well adding struct before structs is perfectly legal C. Therefore some C code also applies to C++. What did you expect? C++ is based on C.
In c++ we avoid using struct before every struct. I've never actually seen it in production code.
Regarding ambiguity, I don't think anyone knows why they allowed that. But I believe it's because the ambiguity is resolved when you add struct. You essentially tell the compiler that this is not a function and therefore that possible meaning is eliminated.

Parsing declarations before definitions in a class

This question here piqued my interest a little. Is there anywhere in the C++ standard that specifies all declarations within a class must be parsed before any accompanying implementations of member functions? I've seen a few other questions similar to this but no references to the standard in any of the answers.
The Standard doesn't specify how the compiler should parse a translation unit. Instead, it specifies everywhere it is and is not valid to use any identifier to refer to a declaration.
3.3.2p5:
After the point of declaration of a class member, the member name can be looked up in the scope of its
class. [ Note: this is true even if the class is an incomplete class. ]
3.3.7p1:
The following rules describe the scope of names declared in classes.
The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration, but also of all function bodies, brace-or-equal-initializers of non-static data members, and default arguments in that class (including such things in nested classes).
A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.
If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.
A name declared within a member function hides a declaration of the same name whose scope extends to or past the end of the member function’s class.
The potential scope of a declaration that extends to or past the end of a class definition also extends to the regions defined by its member definitions, even if the members are defined lexically outside the class (this includes static data member definitions, nested class definitions, member function definitions (including the member function body and any portion of the declarator part of such definitions which follows the declarator-id, including a parameter-declaration-clause and any default arguments (8.3.6).
[class.mem] says:
-2- A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
For the class to be complete within function bodies then in general all declaration need to be parsed: without completely parsing all declaration you can't know if something that wasn't parsed would change the meaning. Although, possibly related to that is [basic.scope.class]/1 which says:
3) If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.
That means certain declarations could be used without parsing the entire class, because if another later declaration altered the meaning then the program would be ill-formed.
Of course the "as if" rule allows the compiler to choose any implementation as long as the user can't tell the difference, so maybe a compiler could choose to parse function bodies and then parse definitions as needed, but it would be hard to tell what's needed to process the member function definition (consider a function call which might call one of several overloaded functions, possibly involving enable_if-type tricks.)
This is the draft which explains C++ Programming Language Standard.
Programming Language C++ PDF
I think page 220 has some explanations on member functions.