Использование полностью определенного имени для пространства имен std в C ++ - PullRequest
0 голосов
/ 17 февраля 2019

Если имя в C ++ не полностью определено, например, std::cout, это может привести к непреднамеренной ошибке, такой как упомянуто в https://en.cppreference.com/w/cpp/language/qualified_lookup. Но использование полностью определенного имени для ::std пространства имен, например, ::std::cout, как я заметил, очень редко

1007 * Есть ли причина, по которой полное имя для ::std пространства имен не используется?

А как насчет использования полного имени для собственногосозданные пространства имен?Это хорошая идея?

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Чтобы поддерживать большой код или лучшую читаемость или конфликт в именах, C ++ предоставил пространство имен "декларативный регион".Определение пространства имен может появляться только в глобальной области видимости или вложено в другое пространство имен.

#Sample Code
#include <iostream>
int main() 
{
      struct std{};
      std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
      ::std::cout << "ok\n"; // OK: ::std finds the namespace std
}

В приведенном выше коде компилятор ищет cout в struct std , но в следующей строке, когда выиспользуйте :: std :: cout он ищет cout в глобально определенном классе std.

Решение:

#include <iostream>
//using namespace std; // using keyword allows you to import an entire namespace at once. 

namespace test
{
    void cout(std::string str)
    {
       ::std::cout<<str; 
    }
}

int main() 
{
    cout("Hello");//'cout' was not declared in this scope
    ::test::cout("Helloo ") ;
    ::std::cout<<"it is also ok\n";
}

Или используйте команду inтаким образом, это просто для лучшей читаемости

##
using namespace test;
int main() 
{
    cout("Hello");//'cout' was not declared in this scope
    cout("Helloo ") ;
    ::std::cout<<"it is also ok\n";
}
0 голосов
/ 17 февраля 2019

Вы совершенно правы в том смысле, что yyyy::xxx может быть неоднозначным, если есть пространство имен yyyy, а также класс yyyy, которые оба видны в одной и той же области видимости.В этом случае только полная квалификация ::yyyy::xxx может решить неоднозначность.Пример вашей ссылки проясняет это:

// from cppreference.com
#include <iostream>
int main() {
  struct std{};
  std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
  ::std::cout << "ok\n"; // OK: ::std finds the namespace std
}

Но на практике сложно создать конфликтующий std на верхнем уровне, так как большинство включений из стандартной библиотеки приведут к сбою:

#include <iostream>

struct std {      // OUCH: error: ‘struct std’ redeclared as different kind of symbol
    int hello;  
}; 

Это означает, что для создания конфликта вам необходимо определить локальные классы или ввести предложение using в другом пространстве имен.Кроме того, никто не посмеет (смел) назвать класс std.

Наконец, на практике ::yyyy::xxx менее удобно читать.Все это объясняет, почему вы не найдете его очень часто.

Дополнительное замечание

Проблема не столько в std, который хорошо известен, а скореедля ваших собственных пространств имен и сторонних библиотек.В этом случае псевдоним пространства имен будет лучшей альтернативой :::yyyy для устранения неоднозначности:

namespace foo {
    void printf() { }
}
int main() {
    foo::printf();          // ok, namespace is chose because no ambiguity
    struct foo {/*...*/ };  // creates ambiguity
    //foo::printf();        // error because struct foo is chosen by name lookup
    ::foo::printf();        // ok, but not if you  decide to move the code to be nested in another namespace
    namespace  mylib = foo ;   // or ::foo (see discussion below)
    mylib::printf();        // full flexibility :-)
}

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

...