Что такое «псевдоним пространства имен» в C ++?

156

Что такое «псевдоним пространства имен» в C ++? Как это используется?

Мартин Б
источник

Ответы:

186

Псевдоним пространства имен - это удобный способ ссылки на длинное имя пространства имен с помощью другого более короткого имени.

Например, скажем, вы хотели использовать числовые векторы из uBLAS Boost без using namespaceдирективы. Указывать полное пространство имен каждый раз громоздко:

boost::numeric::ublas::vector<double> v;

Вместо этого вы можете определить псевдоним для boost::numeric::ublas- скажем, мы хотим сократить это до просто ublas:

namespace ublas = boost::numeric::ublas;


ublas::vector<double> v;
Мартин Б
источник
7
Чтобы объяснить отрицательные стороны, SO не является и никогда не будет заменой хорошего учебника по C ++. На заданный вами вопрос ответит любая такая книга. И так что «особенность» ответа на ваши вопросы не должна использоваться для перефразирования таких книг.
24
Без обид ... Просто, чтобы объяснить, почему я это сделал: из комментариев Джоэла в подкасте было мое понимание того, что даже вопросы "начального уровня" были честной игрой на SO, и что было приемлемо задать вопрос и ответить на него сами, если этот контент не был на SO еще в доступной форме. Но, видимо, это осуждается?
Мартин Б
1
Существует, безусловно, этикет для ответа на свой вопрос, чтобы избежать раздражения; в этом случае совершенно очевидно, что это никогда не было реальным вопросом. Например, stackoverflow.com/questions/494927/…
Марк Гравелл
6
@ Мартин Б: Я не согласен с тем, что это вопрос начального уровня - на самом деле в прошлом задавались гораздо более очевидные вопросы с большим количеством голосов. Сказав это, люди могут почувствовать, что вы просто пытаетесь завоевать репутацию для себя. Обходной путь - пометить один или оба вопроса / ответа как «вики сообщества». Лично я бы пошел с вопросом, как вы, и ответить, как сообщество. Если вопрос имеет смысл, то вы получите ROI.
Ричард Корден
1
Я думаю, что важный вопрос заключается в том, является ли вопрос реальным "- это то, что вам задавали? Это то, что люди хотят знать? Это то, что еще не задавали и не отвечали на SO? Если вы читаете в SO-блоге о том, что сообщество R публикует и отвечает на вопросы здесь, обратите внимание, что они выбрали самые главные вопросы X, которые их сообщество фактически задавало , так что оно имело отношение к реальному миру. Взяв случайные фрагменты знаний по конкретному языку и разместив их здесь, кажется, менее полезный.
Джалф
7

Проще говоря, #define не будет работать.

namespace Mine { class MyClass { public: int i; }; }
namespace His = Mine;
namespace Yours { class Mine: public His::MyClass { void f() { i = 1; } }; }

Компилирует нормально. Позволяет работать с конфликтами имен пространств / классов.

namespace Nope { class Oops { public: int j; }; }
#define Hmm Nope
namespace Drat { class Nope: public Hmm::Oops { void f () { j = 1; } }; }

В последней строке "Hmm: Oops" - ошибка компиляции. Препроцессор меняет его на Nope :: Oops, но Nope уже является именем класса.

user2168377
источник
3
Что такое #define? Возможно, ваш ответ относится к предыдущей версии вопроса?
einpoklum
3

Больше на эту тему http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-1-of-n

Все дело в выборе псевдонима для длинного имени пространства имен, такого как:

namespace SHORT = NamespaceFirst::NameSpaceNested::Meow

Затем позже вы можете набрать

typedef SHORT::mytype

вместо того

typedef NamespaceFirst::NameSpaceNested::Meow::mytype

Этот синтаксис работает только для пространств имен, не может включать классы, типы после namespace NAME =

kiriloff
источник
3

Также обратите внимание, что псевдонимы пространства имен и использование директив разрешаются во время компиляции, а не во время выполнения. (Точнее, оба они используются для указания компилятору, где еще искать при разрешении имен, если он не может найти определенный символ в текущей области или какой-либо из своих родительских областей.) Например, ни один из них не будет компиляции:

namespace A {
    int foo;
    namespace AA {
        int bar;
    } // namespace AA
    namespace AB {
        int bar;
    } // namespace AB
} // namespace A
namespace B {
    int foo;
    namespace BA {
        int bar;
    } // namespace BA
    namespace BB {
        int bar;
    } // namespace BB
} // namespace B

bool nsChooser1, nsChooser2;
// ...

// This doesn't work.
namespace C = (nsChooser1 ? A : B);
C::foo = 3;

// Neither does this.
// (Nor would it be advisable even if it does work, as compound if-else blocks without braces are easy to inadvertently break.)
if (nsChooser1)
    if (nsChooser2)
        using namespace A::AA;
    else
        using namespace A::AB;
else
    if (nsChooser2)
        using namespace B::BA;
    else
        using namespace B::BB;

Теперь любопытный ум мог заметить, что constexprпеременные также используются во время компиляции, и задаться вопросом, могут ли они использоваться в сочетании с псевдонимом или директивой. Насколько мне известно, они не могут, хотя я могу ошибаться по этому поводу. Если вам нужно работать с переменными с одинаковыми именами в разных пространствах имен и выбирать между ними динамически, вам придется использовать ссылки или указатели.

// Using the above namespaces...
int& foo = (nsChooser1 ? A::foo : B::foo);

int* bar;
if (nsChooser1) {
    if (nsChooser2) {
        bar = &A::AA::bar;
    } else {
        bar = &A::AB::bar;
    }
} else {
    if (nsChooser2) {
        bar = &B::BA::bar;
    } else {
        bar = &B::BB::bar;
    }
}

Полезность вышесказанного может быть ограничена, но она должна служить цели.

(Мои извинения за любые опечатки, которые я, возможно, пропустил выше.)

Джастин Тайм - Восстановить Монику
источник
0

Пространство имен используется для предотвращения конфликтов имен.

Например:

namespace foo {
    class bar {
        //define it
    };
}

namespace baz {
    class bar {
        // define it
    };
}

Теперь у вас есть две строки имен классов, которые совершенно разные и отдельные благодаря пространству имен.

«Использование пространства имен», которое вы показываете, заключается в том, что вам не нужно указывать пространство имен для использования классов в этом пространстве имен. то есть std :: string становится строкой.

мой ресурс: https://www.quora.com/What-is-namespace-in-C++-1

маи
источник