Nested namespace definition when the enclosing namespace is inline

556 Views Asked by At

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.

1

There are 1 best solutions below

2
On BEST ANSWER

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).