Как определяется контекст ссылки

Я пытаюсь понять правило раздела 3.4.3.2/3 окончательного рабочего проекта N3797 С++ 14:

Если задано X::m (где X — пространство имен, объявленное пользователем) или задано ::m (где X — глобальное пространство имен), если S(X, m) — пустое множество, программа некорректна. В противном случае, если S(X, m) имеет ровно один элемент или если контекстом ссылки является использование-объявления (7.3.3), S(X, m) является требуемым набором объявлений m. В противном случае, если использование m не позволяет выбрать уникальное объявление из S(X, m), программа некорректна.

Я написал следующий код:

inline namespace A
{
    int i = 42;
};

namespace B 
{
    static const int i = 5;
};

using B::i;

int g= ::i //S(X, i)={using B::i, A::i}

int main() { }

Как сказано в приведенной выше цитате, мы имеем:

[...] если S(X, m) — пустое множество[...]

S(X,m) непусто, далее:

В противном случае, если S(X, m) имеет ровно один элемент

неверно, далее:

или если контекст ссылки является декларацией использования

Я не понимаю, как это ограничение проверяется для моего примера. Я хотел бы понять, как определенный контекст ссылки зависит от использования этой ссылки?


person Community    schedule 20.06.2014    source источник
comment
раздел 3.4.3.2/3 какого документа? У меня есть предположение, но для его подтверждения требуется некоторое время.   -  person Sebastian Mach    schedule 20.06.2014
comment
@phresnel Спасибо за ваше замечание. Я отредактировал свой вопрос.   -  person    schedule 20.06.2014


Ответы (1)


Здесь все просто, хоть и написано сумбурно. Либо имя является членом пространства имен или его встроенных пространств имен, либо имя является именем, введенным директивой using какого-либо другого пространства имен. Если такое имя является ровно одним именем, то оно будет использоваться.

В вашем примере кода S( global, i ) имеет два члена, один из которых определен во встроенном пространстве имен A, а другой вводится с помощью объявления. Так что есть неясность.

Итак, порядок рассмотрения пространств имен следующий. Сначала рассматривается само пространство имен и встраиваемые в него пространства имен. Если имя ровно одно, то оно используется.

В противном случае компилятор рассматривает возможность использования директив. Если снова имя точно одно, оно используется.

Во всех остальных случаях программа некорректна.

Вы должны учитывать предыдущий параграф Стандарта

2 Для пространства имен X и имени m набор поиска S(X,m) с уточнением пространства имен определяется следующим образом: пусть S0(X,m) будет набором всех объявлений m в X и встроенным набором пространств имен X (7.3.1). Если S0(X,m) не пусто, S(X,m) есть S0(X,m); в противном случае S(X,m) является объединением S(Ni,m) для всех пространств имен Ni, назначенных директивами использования в X и его встроенным набором пространств имен.

РЕДАКТИРОВАТЬ: Мне очень жаль. Я смешал использование объявлений и использование директивы. В вашем примере есть использование объявлений. Так что название неоднозначное. Ид вместо

using B::i;

было бы

using namespace B;

тогда не было бы двусмысленности.

Вы должны сравнить два примера

Первый именно тот, что вы показали.

#include <iostream>

inline namespace A
{
    int i = 42;
};

namespace B 
{
    static const int i = 5;
};

using B::i;

int g= ::i;

int main() 
{
    std::cout << g << std::endl;

    return 0;
}

Код не будет скомпилирован, так как S(global, i) содержит два члена.

И другой пример

#include <iostream>

inline namespace A
{
    int i = 42;
};

namespace B 
{
    static const int i = 5;
};

using namespace B;

int g= ::i;

int main() 
{
    std::cout << g << std::endl;

    return 0;
}

Код будет скомпилирован, потому что имя i в пространстве имен B не будет учитываться.

person Vlad from Moscow    schedule 20.06.2014
comment
Спасибо за ответ, но я не согласен со следующим: Using declarations are not considered if the set is not empty.. В 3.4.3.2/2 сказано, что использование директивы не рассматривается, если S(X, m) не пусто. - person ; 20.06.2014
comment
@Dmitry Fucintv Я обновил свой пост. Я перепутал использование объявлений с использованием директивы. Мне жаль. - person Vlad from Moscow; 20.06.2014
comment
Я понял, как определяется S(X, m). Но хотелось бы уточнить, что именно означает правило or if the context of the reference is a using-declaration (7.3.3), S(X, m) is the required set of declarations of m.. И как определяется контекст ссылки. Можете ли вы улучшить свой ответ? - person ; 20.06.2014
comment
@Dmitry Fucintv Нет специального контекста термина. В этой фразе это просто означает, что указанное имя вводится в пространство имен с помощью объявления. То есть, объявляет ли namepsace само имя имени, введенное с помощью объявления. - person Vlad from Moscow; 20.06.2014
comment
Я думаю, что ограничение или if the context of the reference is a using-declaration (7.3.3) не нужны. Это потому, что использование объявления также является объявлением, и я думаю, что это слишком много. Я прав? - person ; 20.06.2014