Я неправильно понимаю, что глава 3 главы 3 раздела «Обзор C++» Бьярна, посвященная пространствам имен, подразумевает, что после использования директивы using мы не можем ее квалифицировать?
Используя директиву using, мы теряем возможность выборочного использования имена из этого пространства имен, поэтому эту возможность следует использовать осторожно, обычно для библиотеки, которая широко распространена в приложении (например, std) или во время перехода для приложения, которое не использовало пространства имен.
Если это не так, то что означает эта цитата? Я не видел, чтобы это было опубликовано во 2-й опечатке. Я протестировал это с помощью этого кода, и он скомпилировался и запустился без каких-либо проблем.
#include <iostream>
using namespace std;
int main()
{
std::cout << "works\n";
}
На самом деле этот отрывок означает, что вы теряете возможность выборочно не использовать имена из этого пространства имен. Теперь они будут найдены путем неквалифицированного поиска, хотите вы этого или нет, тем самым сводя на нет смысл пространств имен, который должен помочь избежать конфликтов имен.
Посмотрите это: C++ Weekly — Ep 305 — Прекратите использовать пространство имен. Это во многом объяснит, почему использование пространства имен имеет свои проблемы. Другой пример: распространенная проблема в Windows заключается в том, что min/max уже являются макросами (из windows.h), и они будут конфликтовать с функциями std::min
/std::max
при использовании using namespace std;
Точка зрения Бьерна прямо противоположна вашей интерпретации. Проблема не в том, что невозможно полностью определить имена — потому что это НИКОГДА невозможно. Проблема в том, что разрешение использования неполных имен становится неоднозначным (поэтому не будет компилироваться), если два или более пространств имен (включая неименованное пространство имен) объявляют одно и то же имя. Если вы не удалите ВСЕ директивы using namespace
, вызывающие неоднозначность, полностью из вашего кода, ЕДИНСТВЕННЫЙ способ устранить эту двусмысленность — использовать полные имена. Это полностью противоречит обычной цели (например, сокращению набора текста) using namespace
.
@BoP, ты это имеешь в виду под std::ranges
? en.cppreference.com/w/cpp/ranges
Да это оно. А если затем добавить два using namespace
, компилятор найдет всего два. Лучше всего не иметь ни одного и указать std::cout
, как в примере в этом вопросе.
Речь идет не об использовании квалифицированных имен, а о неквалифицированных.
Например, если вы используете using namespace std;
с намерением использовать только cout
неполные имена, то вы все равно импортировали и все остальные имена из std
, и все они будут рассматриваться как использование неполных имен. Вы не можете выборочно импортировать только некоторые имена из std
с помощью оператора, и вам нужно это знать.
Например:
#include<iostream>
using namespace std;
void move(long i)
{
cout << "move(" << i << ")\n";
}
int main()
{
move(42);
}
Начиная с C++11, эта программа может печатать move(42)
, а может и не печатать, потому что в стандартной библиотеке есть функция std::move
, которая будет лучше соответствовать разрешению перегрузки для move(42)
, если ее объявление доступно из вызова. И из-за using namespace std;
это std::move
имя библиотеки также становится доступным для неквалифицированного поиска, даже если это не ваше намерение.
Достижимо ли объявление или нет, не указано, поскольку <iostream>
не гарантирует его объявление, но и не обязан его не объявлять.
У вас все еще есть проблемы с неполными именами. Мы видели, как люди открывали новые пространства имен, поэтому добавляли и
using namespace std;
, иusing namespace std::ranges;
, а потом ничего не получалось, потому что большинство имен конфликтуют.