Почему все используют объявленные имена пространства имен (т.е. Std:: not:: std::)?
Мне кажется, что использование незашифрованных пространств имен просто вызывает проблемы позже, когда кто-то помещает новое пространство имен, которое имеет то же имя, что и пространство имен корневого уровня, и загадочно изменяет значение целого ряда программ. Итак, почему люди всегда говорят std::
вместо ::std::
. Неужели они действительно хотят сказать: "Я хочу использовать любую std
, а не корневую."?
Вот пример того, что я имею в виду:
В fred/Foo.h:
#include <string>
namespace fred {
class Foo {
public:
void aPublicMember(const std::string &s);
};
} // end namespace fred
В fred/Bar.h:
namespace fred {
namespace std { // A standard fred component
class string { // Something rather unlike the ::std::string
// ...
};
} // namespace std
class Bar {
public:
void aPublicMember(std::string &s);
};
} // namespace fred
В oops.cpp:
#include <string>
#include "fred/Bar.h"
#include "fred/Foo.h" // Oops, the meaning of Foo is now different.
Это то, чего хотят люди, или я чего-то не хватает?
И, возможно, вы говорите, что вы просто не должны называть пространство имен std
. И это все хорошо и хорошо, но как насчет другого пространства имен корневого уровня? Должно ли любое пространство имен корневого уровня, какое-либо когда-либо определяемое в любом месте, всегда должно быть запрещено для имени под-имен?
Чтобы уточнить, я не буду рассматривать какой-либо ответ, который говорит мне, что std
является особенным, потому что я просто использовал его в качестве примера. Я говорю об общей проблеме, и я использую std
в качестве опоры, чтобы проиллюстрировать ее, хотя я признаю ее довольно поразительной опорой.
Ответы
Ответ 1
Практическая причина для незакрепленных пространств имен заключается в том, что достаточно одного уровня пространств имен. Когда это не так, второй уровень обычно используется для деталей реализации. И, наконец, даже при использовании нескольких уровней они все равно обычно указываются неявно с корневого уровня. то есть. даже внутри пространства имен ns1
, вы обычно ссылаетесь на ns1::ns2::foo
вместо ns2::foo
или ::ns1::ns2::foo
.
Итак, по трем причинам форма ::ns1
избыточна в обычных случаях. Единственный случай, когда я бы подумал, будет в представлении Boost, потому что в качестве автора Boost я не буду знать, где будет использоваться мое программное обеспечение.
Ответ 2
Итак, почему люди всегда говорят std:: вместо:: std::
Возможно, потому, что из-за этого у них никогда не было проблем с двусмысленностью.
В одних и тех же строках: мне никогда не приходилось включать "землю" в мой адрес, и я не собираюсь.
Вы должны нарисовать линию где-то, и это разумное предположение, что другие не будут создавать свои собственные std пространства имен или, по крайней мере, что библиотека, которая делает, не будет очень популярна.:)
Ответ 3
почему люди всегда говорят std::
Не всегда. Я использую string
и using ::std::string
. Так что ничего плохого, если будет fred::std::string
, потому что я все еще использую std::string
. В маленьких cpp файлах это может быть даже using namespace ::std
. Пример:
#include <iostream>
using ::std::string;
//using namespace ::std; // good for small cpp-files
int main()
{
string s = "sometext"; // no leading ::std
}
вы просто не должны называть пространство имен std
Да, вы не должны указывать имя std
для пользовательского пространства имен.
Ответ 4
Это настолько искусственно:
namespace fred {
namespace std { // A standard fred component
class string { // Something rather unlike the ::std::string
// ...
};
} // namespace std
} // namespace fred
Этот Фред не сможет объяснить, почему он сделал это для всей команды.
Чтобы ответить на ваш вопрос: люди опускают сначала "::", потому что это привычка, которая экономит время и потому что легче ожидать, что когда пространство имен используется где угодно, тогда такое имя является абсолютным, а не относительным.
Ответ 5
В случае std
я бы не предполагал другого пространства имен с тем же именем, с теми же классами, но с другим значением.
В других случаях ведущий ::
просто выглядит уродливым и делает код чтения более сложным (на мой взгляд). Столкновения пространства имен слишком редки, чтобы поставить ::
перед всем.
Ответ 6
В глобальном пространстве имен много кода написано. Если кто-то действительно переопределяет:: std::, не имеет значения, как вы относитесь к нему в этом виде кода.
Кроме того, ваш сценарий маловероятен и легко работает. Во-первых, конвенция, так как была "std", заключалась в том, что вы не используете это имя. Во-вторых, если вы столкнулись с пакетом, который определил пространство имен std, вы просто выполните следующее:
#include <package_name.hpp>
namespace package_name {
using namespace std;
}
namespace my_app {
class my_class : public package_name::class_of_something {};
}
Или что-то подобное. Возможно, вам придется явно указывать:: std как std. Я хочу сказать следующее: люди все время используют un-anchored 'std::', потому что даже самые неблагоприятные последствия не имеют большого значения, и вряд ли это возможно.
Ответ 7
Хорошо, вы говорите, что std
- только пример. Но мне кажется, что ваш вопрос применим только к случаю, когда кто-то делает что-то злобное, как переопределение std
.
Позвольте мне привести еще один пример:
namespace logging
{
// Logs to local file
}
namespace server
{
namespace logging
{
// Logs to remote destination
}
}
namespace client
{
namespace logging
{
// Logs to local file and to screen
}
}
В этом случае не добавление ::
приводит к поведению по умолчанию.
Ответ 8
Так же, как зарезервированы имена с префиксом _
, рассмотрите std::
так же хорошо, как зарезервировано.