Reputation: 25641
consider the following code:
struct foo {
typedef int bar;
};
namespace foo {
class baz {
/* code */
};
}
This is spread over a codebase that I have to work on, and it kind of works sometimes and I don't understand how.
As long as the namespace and the class don't occur in the same source (after preprocessing) it will work (I understand that part). However if suddenly both the namespace and the class are dragged into the same compilation unit by the preprocessor it (might) clash (I don't know if this ever occurs in the source).
Is there a convention that allows the compiler to always resolve code structures as those correctly? The most logical would be the forbid by namespaces and classes to have same symbols. The applied coding style allows clashing namespaces with classes albeit the ambiguity thus I would prefer a way to tell the compiler on usage instead of changing the coding convention.
something like:
use_namespace(foo)::baz b;
use_class(foo) b;
Upvotes: 4
Views: 1772
Reputation: 126432
Paragraph 7.3.1/2 of the C++11 Standard simply forbids that:
The identifier in an original-namespace-definition shall not have been previously defined in the declarative region in which the original-namespace-definition appears. The identifier in an original-namespace-definition is the name of the namespace. Subsequently in that declarative region, it is treated as an original-namespacename.
Concerning this statement of yours:
As long as the namespace and the class don't occur in the same source (after preprocessing) it will work
That's incorrect. Paragraph 7.3.2/4 (and the last sentence in particular) tells you why it seems to be "working", although your program is ill-formed:
A namespace-name or namespace-alias shall not be declared as the name of any other entity in the same declarative region. A namespace-name defined at global scope shall not be declared as the name of any other entity in any global scope of the program. No diagnostic is required for a violation of this rule by declarations in different translation units.
This means the codebase you are working with has undefined behavior, and this is potentially a time bomb that may explode in incomprehensible ways.
Upvotes: 11
Reputation: 254461
As long as the namespace and the class don't occur in the same source (after preprocessing) it will work (I understand that part).
No it doesn't. Declaring the same name for two different entities gives undefined behaviour according to C++11 3.3.1/4:
Given a set of declarations in a single declarative region, each of which specifies the same unqualified name, they shall all refer to the same entity
(with some exceptions which do not include giving a class and a namespace the same name).
Since the declarations are in separate translation units, many compilers can't diagnose the error, so it might appear to work.
However if suddenly both the namespace and the class are dragged into the same compilation unit by the preprocessor it (might) clash (I don't know if this ever occurs in the source).
Now that they are in the same translation unit, the error can be diagnosed.
Upvotes: 2