c++ 出现在同一个实体的不同定义中的lambda表达式会产生相同的闭包类型吗?

oymdgrw7  于 2023-01-28  发布在  其他
关注(0)|答案(1)|浏览(108)

在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在这一点上有错吗?

cbjzeqam

cbjzeqam1#

是的,闭包类型在所有翻译单元中都是相同的,编译器仍然在追赶这一点。这样做的 * 机制 * 是从闭包类型在整个定义中的位置为闭包类型生成(损坏的)名称(通过,比如说,计数它们,如评论中所提到的)。标准中的 * 原因 * 有点微妙。

[basic.def.odr]/13.10未规定封闭类型相同;它使用了“shall”,因此 * 要求 * 它们是相同的(考虑到下面的情况,这只在更微妙的情况下才有效果),而/14具有这样的效果:“行为就好像有一个单一的实体有一个单一的定义”,这必然会产生一个单一的闭包类型。即使这样,说lambda表达式“产生相同的闭包类型”也是不恰当的:相反,所产生的闭包类型中只有一个与整个程序有任何相关性。
请注意,如果没有这样的规定,简单函数(如

#ifndef MY_HEADER_HH
#define MY_HEADER_HH

inline auto make_assign(int i) {return [i](int &x) {x=i;};}

#endif

如果多个翻译单元试图将不同的make_assign(…)对象添加到std::vector<decltype(make_assign(0))>中,那么这种方法就无法工作。

相关问题