inline namespace and extension namespace
Asked Answered
E

2

9

I read the section about namespace definition. Clause 7.3.1 of N3797 said:

The inline keyword may be used on an extension-namespace-definition only if it was previously used on the original-namespace-definition for that namespace.

Consider the following code snippet:

namespace M
{
    int h;
}

inline namespace M
{
    int j = 6;
}

It compiled successful both with the -std=c++11 and without that option. Can you explain that behavior? Is it a g++ bug?

Erogenous answered 14/6, 2014 at 11:59 Comment(0)
R
6

Vour reference to the standard is explicit: this is not allowed.

Using Clang++ I get the very clear error message about this:

Test0614-1.cpp:17:18: error: non-inline namespace cannot be reopened as inline
inline namespace M
                 ^
Test0614-1.cpp:12:11: note: previous definition is here
namespace M
          ^

So it's definitively a bug in g++. By the way, it's reported here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53402

The fact that the compiler accepts inline namespace for previous version of the standard and without at least a warning seems to be an issue. This was already reported as bug in 2010 and should have been fixed: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43824

Readus answered 14/6, 2014 at 13:49 Comment(0)
L
0
namespace M
{
    int h;
}

inline namespace M
{
    int j = 6;
}

This will cause the error 'non-inline namespace cannot be opened as an inline namespace

You have to use:

inline namespace M
{
    int h;
}

inline namespace M
{
    int j = 6;
}

The other way around, you should just get a warning that you are reopening an inline namespace as a non-inline namespace

inline namespace M
{
    int h;
}

namespace M
{
    int j = 6;
}

But it doesn't change anything at all from what I can tell so I don't know why the warning exists, but the fact it exists and ::inline suggests otherwise.

namespace M
{
    inline namespace F {
        int h;
    }
}

namespace M::F {
    int k;
}

gives the same warning, which is suppressed when using:

namespace M::inline F {
    int k;
}

Interestingly, this is illegal:

inline namespace M
{
    inline namespace F {
        int h;
    }
}

inline namespace M::inline F {
    int k;
}

You can either use namespace M::inline F or namespace M::F but you will get a warning in both cases that you are opening inline namespace M as a non-inline namespace.

It may just be that ::inline only exists to suppress that warning and to make the programmer aware from the extension namespace that it is an inline namespace that can be accessed without a scope resolution operator without them having to check the main namespace definition, which makes the code and intention clear, and because most inline namespaces are used for versioning where they are always nested inside a non-inline namespace at global namespace scope, the syntax inline namespace M::inline F wasn't needed to be allowed. Previously namespace M {inline F {int k;}} had to be used instead of namespace M::F to make that intention clear on the extension namespace block.

Lythraceous answered 3/6, 2020 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.