Почему встроенные безымянные пространства имен?

Быстрый для гуру: C ++ 11 позволяет объявлять безымянные пространства имен inline, Это кажется излишним для меня; вещи, объявленные в безымянном пространстве имен, уже используются так, как если бы они были объявлены во вложенном пространстве имен.

Итак, мой вопрос заключается в следующем: что это значит сказать

inline namespace /*anonymous*/ {
// stuff
}

и чем он отличается от традиционного

namespace /*anonymous*/ {
// stuff
}

что мы знаем и любим из C ++ 98? Может ли кто-нибудь привести пример другого поведения, когда inline используется?

РЕДАКТИРОВАТЬ: Просто чтобы уточнить, так как этот вопрос был отмечен как дубликат: я не спрашиваю о названный встроенные пространства имен в целом. Я понимаю вариант использования и думаю, что они великолепны. Я специально спрашиваю, что значит объявить неназванный пространство имен как inline, Поскольку безымянные пространства имен обязательно всегда локальны для TU, рациональное управление версиями символов, кажется, не применимо, поэтому мне любопытно, что добавить inline на самом деле делает.


Кроме того, стандарт [7.3.1.1], касающийся безымянных пространств имен, гласит:

inline появляется, если и только если он появляется в Неназванный-пространства имен-определение

но это кажется тавтологией для моих глаз неязыкового юриста — «оно появляется в определении, если оно появляется в определении»! Что касается бонусных баллов, кто-нибудь может объяснить, что на самом деле говорит этот бит стандарта?

РЕДАКТИРОВАТЬ: Cubbi требовал бонусного балла в комментариях:

стандарт говорит, что Неназванный-пространства имен-определение ведет себя так, как будто он был заменен Икс где inline появляется в Икс если он появляется в Неназванный-пространства имен-определение

18

Решение

Вот одно использование, которое я нашел:

namespace widgets { inline namespace {

void foo();

} } // namespaces

void widgets::foo()
{
}

В этом примере foo имеет внутреннюю связь, и мы можем определить функцию позже, используя namespace::function синтаксис для проверки правильности подписи функции. Если бы вы не использовали widgets пространство имен, то void foo() определение будет определять совершенно другую функцию. Вам также не нужно повторно открывать пространство имен, сохраняя уровень отступа.

Если есть другая функция с именем foo в виджетах namespace уже тогда это даст вам двусмысленность, а не неприятное нарушение ODR.

7

Другие решения

Я не знаю, стоит ли отвечать на ваш собственный вопрос о SO, но после некоторой игры вокруг мое любопытство было удовлетворено, так что я могу также поделиться им.

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

inline // comment this out to change behaviour
namespace {
template <typename T> struct A {};
}

template <> struct A<int> {};

Без inline, g ++ жалуется на попытку специализировать шаблон из другого пространства имен (хотя Clang этого не делает). С inline, это компилируется просто отлично. В обоих компиляторах все, что определено в специализации, все еще помечается как имеющее внутренняя связь (в соответствии с nm), как если бы это было в пределах безымянного пространства имен, но я думаю, этого следовало ожидать. Я не могу придумать причину, почему это было бы полезно, но мы идем.

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

namespace NS {
// Pretend this is defined in some header file
template <typename T>
void func(const T&) {}

// Some type definition private to this TU
inline namespace {
struct A {};
}

} // end namespace NS

int main()
{
NS::A a;
func(a);
}

Без inline, ADL терпит неудачу, и мы должны явно написать NS::func(a), Конечно, если бы мы определили безымянное пространство имен на верхнем уровне (как обычно), мы бы не получили ADL, независимо от того, было ли оно встроенным или нет, но все же …

8

По вопросам рекламы [email protected]