Gurus的快速版本:C ++ 11允许声明未命名的命名空间inline
。这对我来说似乎是多余的;在未命名的命名空间中声明的内容已被使用,就像它们是在封闭的命名空间中声明一样。
所以我的问题是:说什么意思
inline namespace /*anonymous*/ {
// stuff
}
它与传统的
有什么不同namespace /*anonymous*/ {
// stuff
}
我们从C ++ 98中了解和喜爱?任何人都可以在使用inline
时给出不同行为的示例吗?
编辑:只是为了澄清,因为这个问题已被标记为重复:我一般不会询问命名内联命名空间。我理解那里的用例,我认为它们很棒。我特别询问将未命名的名称空间声明为inline
意味着什么。由于未命名的命名空间必然始终是TU的本地命名空间,因此符号版本的理性似乎不适用,所以我很好奇添加inline
实际上做了什么。
另外,关于未命名的命名空间的标准[7.3.1.1]说:
中时才会出现
inline
当且仅当它出现在 unnamed-namespace-definition
但这对我的非语言律师的眼睛来说似乎是一种同义反复 - “它出现在定义中,如果它出现在定义中”!对于奖励积分,任何人都可以解释一下这些标准实际上在说什么吗?
编辑: Cubbi在评论中声称获得了奖励积分:
标准是说 unnamed-namespace-definition 的行为好像被 X 所取代,其中
中inline
出现在 X iff它出现在 unnamed-namespace-definition
答案 0 :(得分:8)
这是我找到的一个用途:
namespace widgets { inline namespace {
void foo();
} } // namespaces
void widgets::foo()
{
}
在此示例中,foo
具有内部链接,我们可以稍后使用namespace::function
语法定义函数,以确保函数的签名正确。如果您不使用widgets
命名空间,则void foo()
定义将定义完全不同的函数。您也无需重新打开命名空间,从而节省了一定程度的缩进。
如果小部件foo
中还有另一个名为namespace
的函数,那么这将使您产生歧义,而不是令人讨厌的ODR违规。
答案 1 :(得分:8)
我不知道在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,无论它是否是内联的,但仍然......