在C20中,我们可以在未求值的上下文中使用lambda表达式。考虑下面的C20代码:
foo.cpp
#include <typeinfo>
struct Foo {
using T = decltype([]{});
}; // struct Foo
const std::type_info& getType() { return typeid(typename Foo::T); }
main.cpp
#include <iostream>
#include <typeinfo>
struct Foo {
using T = decltype([]{});
}; // struct Foo
const std::type_info& getType();
const std::type_info& getTypeFromMain() { return typeid(typename Foo::T); }
int main() {
std::cout << std::boolalpha
<< (getType() == getTypeFromMain());
return 0;
}
在标准C++下程序应该输出什么?
GCC和clang输出false
,他们认为所有的lambda表达式应该产生不同的闭包类型,并且对于翻译单元是“本地的”。
另一方面,[basic.def.odr] 13.10声明,同一实体在不同翻译单元内的不同定义中对应的lambda表达式引入的闭包类型应该相同,程序应该输出true
,GCC和clang在这一点上有错吗?
1条答案
按热度按时间cbjzeqam1#
是的,闭包类型在所有翻译单元中都是相同的,编译器仍然在追赶这一点。这样做的 * 机制 * 是从闭包类型在整个定义中的位置为闭包类型生成(损坏的)名称(通过,比如说,计数它们,如评论中所提到的)。标准中的 * 原因 * 有点微妙。
[basic.def.odr]/13.10未规定封闭类型相同;它使用了“shall”,因此 * 要求 * 它们是相同的(考虑到下面的情况,这只在更微妙的情况下才有效果),而/14具有这样的效果:“行为就好像有一个单一的实体有一个单一的定义”,这必然会产生一个单一的闭包类型。即使这样,说lambda表达式“产生相同的闭包类型”也是不恰当的:相反,所产生的闭包类型中只有一个与整个程序有任何相关性。
请注意,如果没有这样的规定,简单函数(如
如果多个翻译单元试图将不同的
make_assign(…)
对象添加到std::vector<decltype(make_assign(0))>
中,那么这种方法就无法工作。