Контекст использования объявления и неоднозначного объявления

#c #namespaces #language-lawyer

#c #пространства имен #язык-юрист

Вопрос:

Существует цитата из раздела 3.4.3.2 / 3:

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

Определение S(X,m) приведено в следующем разделе. 3.4.3.2 / 2:

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

Теперь рассмотрим следующий код:

 #include <iostream>

using namespace std;
namespace N
{
    int cout = 6;
}
using namespace N;

int main() {
    using ::cout;//error: reference to ‘cout’ is ambiguous
    return 0;
}
  

Я не понимаю эту ошибку. Приведенный выше код не противоречит правилу:

если S(X, m) имеет ровно один элемент, или если контекст ссылки представляет собой using-declaration (7.3.3), S(X, m) — это требуемый набор объявлений m.

Можете ли вы объяснить смысл этого правила?

Комментарии:

1. Вы забыли упомянуть, что cout вы ожидали от этого using предложения для идентификации.

2. Для функций набор всех объявлений с несколькими значениями (может) не иметь конфликта и двусмысленности, для классов и экземпляра объекта неясно, какой из них вы хотите.

Ответ №1:

Дмитрий, я подозреваю, что вы неверно истолковываете, что означает «если контекст ссылки является using-declaration«. «В контексте using-declaration» не означает «при использовании в using-declaration«. Вместо этого это означает «когда ссылка является предметом using-declaration«. Предположим, что ваш код изменен следующим образом:

 int main() {
    using N::cout;
    std::cout << "value=" << cout << 'n';
}
  

Обратите внимание на использование неквалифицированного cout in std::cout << "value=" << cout << 'n' . Контекстом этой неквалифицированной ссылки является using-declaration using N::cout .

Другой способ взглянуть на то, что означает стандарт, заключается в том, что using-declaration имеет приоритет над using-directive .