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:
The only rule we have, from [namespace.def]/3, is (emphasis mine):
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 isinline
, 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:And the same would be true if you harmonized the leading
inline
with the nestedinline
by putting it on the other side ofnamespace
: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 likenamespace ::inline N::inline M
but that's just weird in its own way).