Consider the following demonstrative program
#include <iostream>
inline namespace A
{
}
namespace A:: inline B
{
void f() { std::cout << "Hello nested namespace definition.\n"; }
}
int main()
{
f();
return 0;
}
The result of the compilation of the program by the compiler clang HEAD 11.0.0
is the following
prog.cc:7:11: warning: inline namespace reopened as a non-inline namespace
namespace A:: inline B
^
inline
prog.cc:3:18: note: previous definition is here
inline namespace A
^
1 warning generated.
Hello nested namespace definition.
But according to the grammar of the nested namespace definition I may not use the keyword inline
before the namespace A.
So is it a bug of the compiler or am I doing something wrong?
By the way the compiler gcc HEAD 10.0.1 20200
compiles the program without any warning.
The fixit-hint for clang is misleading (since you cannot actually do the thing it is telling you to do), but the program is fine (although misleading, since it looks like you're declaring a non-inline namespace when you're really not - so the warning isn't entirely unreasonable).
Ignoring nested namespaces for the moment, this is actually fine:
inline namespace N { int i=0; };
namespace N { int j=1; };
int k=j;
The only rule we have, from [namespace.def]/3, is (emphasis mine):
The
inline
keyword may be used on a namespace-definition that extends a namespace only if it was previously used on the namespace-definition that initially declared the namespace-name for that namespace.
The wording is "only if", not "if and only if" - so you can't mark a namespace inline
that was previously not marked... but if the first declaration of a namespace is inline
, not every subsequent declaration has to be.
As noted in OP, clang warns on this anyway. Because it's kind of misleading.
But why can't we just stick a leading inline
in there?
As described in the paper, the problem with allowing nested namespace with the leading namespace inline
is that it leads to ambiguity for programmers:
inline namespace std::experimental::parallelism_v2; // not immediately to reader,
// is std or parallelism_v2 inline?
And the same would be true if you harmonized the leading inline
with the nested inline
by putting it on the other side of namespace
:
namespace inline std::experimental::parallelism_v2; // immediately to reader?
// std or parallelism_v2 inline?
So it's imply not supported. If you want a nested namespace with the top-level namespace inline
... you can't. The top-level namespace must be non-inline
(I suppose we could've considered syntax like namespace ::inline N::inline M
but that's just weird in its own way).