Расширение пространства имен во встроенном пространстве имен, которое первоначально было определено во вложенном пространстве имен встроенного пространства имен - PullRequest
2 голосов
/ 23 октября 2019

Я хотел бы проверить, правильно ли я понимаю приведенную ниже цитату из стандарта C ++ 20 (английский не является моим родным языком).

Раздел 9.7.1 Определение пространства имен:

2 В именованном-пространстве-имен-идентификаторе идентификатор - это имя пространства имен. Если идентификатор при поиске (6.4.1) относится к имени пространства имен (но не к псевдониму пространства имен), которое было введено в пространство имен, в котором появляется определение именного пространства имен, или которое было введено в элементевстроенный набор пространств имен этого пространства имен, определение пространства имен расширяет ранее объявленное пространство имен. В противном случае идентификатор вводится как имя пространства имен в декларативную область, в которой появляется определение именованного пространства имен.

То есть пространство имен может быть определено в пространстве имен и затем расширено в одном из его встроенныхПространство имен? Или наоборот. Может ли пространство имен быть определено во встроенном пространстве имен и затем расширено во включающем его пространстве имен?

Вот демонстрационная программа.

#include <iostream>

inline namespace N1
{
    inline namespace N2
    {
        namespace N3
        {
            void f( int ) { std::cout << "f( int )\n"; }
        }
    }

    namespace N3
    {
        void f( char ) { std::cout << "f( char )\n"; }
    }        
}

int main()
{
    N3::f( 10 );
    N3::f( 'A' );
}

Выходные данные программы:

f( int )
f( char )

Однако для этой программы компилятор выдает ошибку о том, что ссылка на 'N3' неоднозначна.

#include <iostream>

inline namespace N1
{
    namespace N3
    {
        void f( int ) { std::cout << "f( int )\n"; }
    }

    inline namespace N2
    {
        namespace N3
        {
            void f( char ) { std::cout << "f( char )\n"; }
        }        
    }
}

int main()
{
    N3::f( 10 );
    N3::f( 'A' );
}

Ответы [ 2 ]

2 голосов
/ 23 октября 2019

может ли пространство имен быть определено в пространстве имен и затем расширено в одном из его встроенных пространств имен?

Нет. Во втором примере, когда компилятор видит определение N3 внутри N2, поиск N3 находит N3, который был объявлен вне N2, но что N3 не было "введено впространство имен, в котором появляется именованное-пространство имен-определений "(поскольку оно не внутри N2), или" введено в элемент набора встроенных пространств имен этого пространства имен ", поскольку набор встроенных пространств имен N2 является набором транзитивновстроенные пространства имен внутри N2. Таким образом, это новое определение N3 не расширяет предыдущее.

Может ли пространство имен быть определено во встроенном пространстве имен, а затем расширено во включающем его пространстве имен?

Да. В вашем первом примере N3 при поиске находит N2::N3, который был «введен в член набора встроенных пространств имен», поскольку N2 является частью набора встроенных пространств имен N1.

Мы можем понять обоснование этой кажущейся асимметрии следующим образом: во втором примере, когда N3 изначально определен, он определяется как член N1, а не член любого встроенного пространства именN1. Позже, когда определяется N2::N3, если он будет расширяться N1::N3, это будет задним числом , что сделает N3 членом N2, что противоречит здравому смыслу и поэтому запрещено. В первом примере N3 первоначально определяется как член встроенного пространства имен N2, и нет проблемы с его расширением вторым определением позже. (Хотя я не вижу очевидной причины, почему это полезно.)

2 голосов
/ 23 октября 2019

Я попытаюсь переписать стандартную формулировку менее плотным (но, возможно, менее точным) способом:

  1. Мы находимся в лексическом пространстве X.

  2. Мы сталкиваемся с чем-то похожим на namespace Y { ... }.

  3. Мы смотрим вверх Y. Если Y не является именем пространства имен, перейдите на 1 .

  4. Был ли Y введен (непосредственно) в X? Если это так, перейдите к пункту 6.

  5. Был ли введен Y в пространство имен, которое является частью встроенного набора 2 пространств имен X? Если да, переходите к 6. Если нет, переходите к 1 .

  6. Y расширяет пространство имен, найденное на шаге 3.

1 "Двигаться дальше" в смысле "игнорировать цитируемый стандартный параграф" .
2 Встроенный набор пространств имен N является транзитивным замыканием всех встроенных пространств имен в N.

, может быть пространство именопределены в пространстве имен и затем расширены в одном из его встроенных пространств имен?

Нет. Мы учитываем только непосредственно включенное пространство имен (N3 расширено в N1 в вашем первом примере и N2 во втором) и его встроенные пространства имен. Вот почему ваш второй пример не работает: N2 (или его встроенный набор пространств имен) не содержит какого-либо предыдущего определения N3.

Может ли пространство имен быть определено во встроенном пространстве имени затем быть расширены во включающем его пространстве имен?

Да.

Приведенные вами примеры соответствуют стандартной формулировке.

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