Определение вложенного пространства имен, когда внутреннее пространство имен является встроенным - PullRequest
0 голосов
/ 23 апреля 2020

Рассмотрим следующую демонстрационную программу

#include <iostream>

inline namespace A
{
}

namespace A:: inline B
{
    void f() { std::cout << "Hello nested namespace definition.\n"; }
}

int main() 
{
    f();

    return 0;
}

Результатом компиляции программы компилятором clang HEAD 11.0.0 будет следующее

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.

Но в соответствии с грамматикой Определение вложенного пространства имен Я не могу использовать ключевое слово inline перед пространством имен A.

Так это ошибка компилятора или я что-то не так делаю?

Кстати, компилятор gcc HEAD 10.0.1 20200 компилирует программу без предупреждения.

1 Ответ

1 голос
/ 23 апреля 2020

Исправление подсказки для clang вводит в заблуждение (поскольку вы на самом деле не можете делать то, о чем вам говорят), но программа в порядке (хотя и вводит в заблуждение, поскольку похоже, что вы объявляете не встроенное пространство имен, когда на самом деле это не так, поэтому предупреждение не является абсолютно необоснованным).

Игнорирование вложенных пространств имен на данный момент, на самом деле это нормально:

inline namespace N { int i=0; };
namespace N { int j=1; };
int k=j;

Единственное правило, которое у нас есть, из [namespace.def] / 3 , (выделено мной) :

Ключевое слово inline может использоваться в определении пространства имен , которое расширяет пространство имен , только если ранее использовалось в определение пространства имен , которое первоначально объявило имя пространства имен для этого пространства имен.

Формулировка "только если", а не "если и только если" - так вы не может пометить пространство имен inline, которое ранее не было помечено ... но если первое объявление пространства имен inline, не каждое последующее объявление должно быть.

Как отмечено в OP, clang предупреждает об этом в любом случае. Потому что это вводит в заблуждение.

Но почему мы не можем просто вставить туда ведущий inline?

Как описано в документе , проблема с разрешением использования вложенного пространства имен с выводом namespace inline в том, что это приводит к неоднозначности для программистов:

inline namespace std::experimental::parallelism_v2;  // not immediately to reader,
                                                     // is std or parallelism_v2 inline?

И то же самое будет верно, если вы гармонизируете ведущий inline с вложенным inline, помещая его в другой сторона namespace:

namespace inline std::experimental::parallelism_v2;  // immediately to reader?
                                                     // std or parallelism_v2 inline?

Так что это не поддерживается. Если вам нужно вложенное пространство имен с пространством имен верхнего уровня inline ... вы не можете. Пространство имен верхнего уровня должно быть не inline (полагаю, мы могли бы рассмотреть синтаксис наподобие namespace ::inline N::inline M, но это по-своему странно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...