Почему все используют незанятые объявления пространства имен (т.е. std :: not :: std: :)? - PullRequest
26 голосов
/ 02 ноября 2009

Мне кажется, что использование незанятых пространств имен просто вызывает проблемы позже, когда кто-то вставляет новое пространство имен, которое, как оказалось, имеет то же имя, что и пространство имен корневого уровня, и таинственным образом изменяет значение целого ряда программ. Итак, почему люди всегда говорят 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 в качестве опоры, чтобы проиллюстрировать ее, хотя признаю, что это довольно поразительная опора.

Ответы [ 8 ]

36 голосов
/ 02 ноября 2009

Итак, почему люди всегда говорят, std :: вместо :: std ::

Возможно, потому что у них никогда не было проблем с двусмысленностью из-за этого.

В том же духе: мне никогда не приходилось включать «землю» в свой адрес, и я не собираюсь этого делать.

Вы должны провести черту где-то, и это разумное предположение, что другие не будут создавать свои собственные пространства имен std, или, по крайней мере, библиотека, которая не будет очень популярной. :)

19 голосов
/ 02 ноября 2009

Практическая причина незанятых пространств имен заключается в том, что обычно достаточно одного уровня пространств имен. Когда это не так, второй уровень обычно будет использоваться для деталей реализации. И, наконец, даже при использовании нескольких уровней они все же обычно указываются неявно от корневого уровня. то есть. даже внутри пространства имен ns1 вы обычно ссылаетесь на ns1::ns2::foo вместо ns2::foo или ::ns1::ns2::foo.

Итак, по этим трем причинам форма ::ns1 в нормальных случаях является избыточной. Единственный случай, когда я рассмотрю это, будет в материалах Boost, потому что как автор Boost я не буду знать, где будет использоваться мое программное обеспечение.

7 голосов
/ 02 ноября 2009

почему люди всегда говорят 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 пользовательскому пространству имен.

3 голосов
/ 02 ноября 2009

Хорошо, вы говорите, что 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
    }
}

В этом случае не добавление :: приводит к поведению по умолчанию.

3 голосов
/ 02 ноября 2009

Это настолько искусственно:

namespace fred {
namespace std {  // A standard fred component

class string { // Something rather unlike the ::std::string
   // ...
};

} // namespace std
} // namespace fred

Этот Фред не сможет объяснить, почему он так поступил со всей командой.

Чтобы ответить на ваш вопрос: люди сначала опускают "::", потому что это привычка, которая экономит время и потому что легче ожидать, что когда пространство имен используется где-либо, такое имя является абсолютным, а не относительным.

2 голосов
/ 02 ноября 2009

Много кода написано в глобальном пространстве имен. Если кто-то действительно переопределит :: 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. Моя точка зрения такова: люди все время используют не привязанный 'std ::', потому что даже наихудшие последствия не имеют большого значения, и вряд ли в этом.

2 голосов
/ 02 ноября 2009

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

В других случаях ведущий :: выглядит просто некрасиво и затрудняет чтение кода (на мой взгляд). Столкновения в пространстве имен слишком редки, чтобы поставить перед собой ::.

1 голос
/ 02 ноября 2009

Точно так же, как имена с префиксом _ зарезервированы, рассмотрите std:: как зарезервированное.

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