2013-11-26 9 views
17

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

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

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

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

namespace /*anonymous*/ { 
    // stuff 
} 

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

EDIT: Просто для уточнения, так как этот вопрос был отмечен как дубликат: Я не спрашиваю о имени встроенных пространств имен в целом. Я понимаю прецедент, и я думаю, что они здорово. Я специально спрашивать, что это значит объявить неназванного имена, как inline. Так как безымянные пространства имена обязательно всегда локальны по отношению к ТОМУ, символу контроля версий рациональны, кажется, не применяется, поэтому мне любопытно, что добавление inlineна самом деле делают.


Как и в стороне, стандарт [7.3.1.1], в отношении неназванных пространств имен, говорит:

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

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

EDIT: Cubbi утверждал бонусный балл в комментариях:

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

+0

Возможный дубликат [Что такое встроенные пространства имен для ?] (http://stackoverflow.com/questions/11016220/what-are-inline-namespaces-for) – Shoe

+0

@Jefffrey, Это о * неназванных * внутренних пространствах имен. – chris

+0

@chris, я думаю, вы можете смешать определение * unnamed * и * inline * namespaces, чтобы придумать ответ. – Shoe

ответ

7

Вот одна польза, что я нашел:

namespace widgets { inline namespace { 

void foo(); 

} } // namespaces 

void widgets::foo() 
{ 
} 

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

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

+0

Я не уверен, что понимаю, что вы здесь делаете. Зачем нужно внутреннее 'inline namespace'? – templatetypedef

+0

@templatetypedef внутреннее 'inline namespace' дает внутреннюю связь' foo'. Внешнее «пространство имен» состоит в том, что вы можете использовать синтаксис 'namespace :: function', чтобы определить его, чтобы вы правильно поняли подпись. – Simple

+0

А, это имеет смысл. Возможно, вы захотите обновить свой ответ, чтобы явно указать это, так как я не выбрал это в первый раз. – templatetypedef

7

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

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

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

template <> struct A<int> {}; 

Без inline, г ++ жалуется пытаюсь специализировать шаблон из другого пространства имен (хотя 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 независимо от того, была ли она встроенной или нет, но все же ...

Смежные вопросы