最近构建的GCC 4.8在头文件中给出了以下代码:
auto L = [](){};
struct S
{
decltype(L) m;
};以下警告:
test.hpp:3:8: warning: 'S' has a field 'S::m' whose type uses the anonymous namespace [enabled by default]
struct S
^为什么编译器考虑使用匿名命名空间的lambda类型?我使lambda成为全局的,我在任何地方都没有使用匿名名称空间。
UPDATE:即使我将lambda放置在显式命名空间中,编译也会发出相同的警告,如下所示:
namespace N
{
auto L = [](){};
}
struct S
{
decltype(N::L) m;
};更新2:实际上,类作用域lambda似乎也有相同的问题:
class N
{
static constexpr auto L = [](){};
};
struct S
{
decltype(N::L) m;
};发布于 2012-07-18 22:22:28
GCC的警告可能有点令人困惑,但它的意图肯定是正确的。lambda的类型是未命名的,它在整个程序中是唯一的。另一方面,如果您的类没有放在一个未命名的命名空间中(根据您的描述,我认为没有),那么您的类在包含它的每个翻译单元中都是相同的类型。因为同一个类应该有相同的成员,而不是不同翻译单元中的不同成员,这是一种违反(并导致未定义的行为)。
至少同样糟糕的是,L是extern,因此一旦将标题包含到多个翻译单元中,就会得到“L的多个定义”链接器错误。
发布于 2012-07-18 04:37:49
第5.1.2/3号编:
lambda-表达式的类型(它也是闭包对象的类型)是一个唯一的、未命名的非联合类类型(称为闭包类型),其属性如下所述。这个类类型不是一个聚合(8.5.1)。闭包类型在包含相应lambda表达式的最小块作用域、类作用域或命名空间范围中声明。
因此,除非在匿名命名空间中用代码定义lambda表达式,否则不应该将lambda的类型包含在匿名命名空间中。
发布于 2012-07-18 04:41:20
除非我遗漏了什么,否则它们都不应该出现在一个匿名的名称空间中,尽管GCC和MSVC似乎都把它们放在了那里。
§5.1.2 [expr.prim.lambda] p3
..。闭包类型在包含相应lambda表达式的最小块作用域、类作用域或命名空间范围中声明。..。
至少Clang似乎是正确的,闭包类型驻留在它应该在的位置。
(您可以通过简单地在某种类型的警告/错误生成代码中包含lambda来测试lambda类型驻留在哪个名称空间中。编译器应该将其类型与警告/错误一起显示出来。)
https://stackoverflow.com/questions/11534265
复制相似问题