Consider
namespace M {
void f();
struct S;
}
namespace N {
void M::f() {}
struct M::S {};
}
This code is rejected by all compilers I tested, because M::f
and M::S
are only allowed to be defined in an enclosing scope. The standard also contains an example that implies that a function may only be defined in an enclosing scope.
However, I can't figure out where in the standard to find the actual rule. In C++20 there was [class.pre]/3:
If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set (9.8.2) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the class-head-name of the definition shall not begin with a decltype-specifier.
There was also a rule about member functions, but I couldn't find one for free functions. P1787R6 removed the wording shown above, but the replacement wording doesn't seem to imply the same restriction. Here's what [class.pre] says in the C++23 draft:
If a class-head-name contains a nested-name-specifier, the class-specifier shall not inhabit a class scope. If its class-name is an identifier, the class-specifier shall correspond to one or more declarations nominable in the class, class template, or namespace to which the nested-name-specifier refers; they shall all have the same target scope, and the target scope of the class-specifier is that scope. [...]
In the example above, the nested-name-specifier M::
in the attempted definition of M::S
denotes the namespace M
, and S
is nominable in M
at this point because S
was previously declared in M
; [basic.scope.scope]/6.
Since I can't find any rule in the C++23 draft to forbid definitions in non-enclosing scopes, I might think that P1787R6 made it allowed. However, since compilers still don't accept this code, I think it's more likely that the rule still exists but is in some place that I've missed (or is phrased more subtly than it used to be).
A declaration that uses a declarative nested-name-specifier shall be a friend declaration or inhabit a scope that contains the entity being redeclared or specialized.
Where your two redeclarations do not "inhabit a scope that contains the entity being redeclared or specialized". (Your original declarations inhabit the namespace scope ::M
, and the defining declarations inhabit ::N
, where ::N
does not contain ::M
).