由于 C++20 lambda 函数在未计算的上下文中是允许的,特别是它们应该被允许在decltype
和sizeof
表达式中。
反过来,lambda 可以在它们的主体中定义一些类型以及这些类型的可能返回对象,例如:
using T = decltype( []{ struct S{}; return S{}; } );
[[maybe_unused]] constexpr auto N
= sizeof( []{ struct S{}; return S{}; } );
Clang 接受此代码,但 GCC 发出错误:
error: types may not be defined in 'decltype' expressions
1 | using T = decltype( []{ struct S{}; return S{}; } );
error: types may not be defined in 'sizeof' expressions
4 | = sizeof( []{ struct S{}; return S{}; } );
演示:https : //gcc.godbolt.org/z/9aY1KWfbq
哪一个编译器就在这里?
自P0315R4 起删除的未评估上下文中对 lambda 的限制意味着这不被禁止(尽管是极端情况),因此可以说 GCC 在这里有一个错误。特别是论文中的以下讨论与此处相关:
此外,在核心反射器上提出了一些关于重新声明的问题,如下所示:
template <int N> static void k(decltype([]{ return 0; }())); template <int N> static void k(decltype([]{ return 0; }())); // okay template <int N> static void k(int); // okay
这些应该是有效的重新声明,因为 lambda 表达式被评估,并且它们的主体中既不包含模板参数,也不是包含模板参数的完整表达式的一部分。因此,lambda 表达式不需要出现在函数的签名中,其行为与此等效,无需任何特殊措辞:
struct lambda { auto operator()() const { return 0; } }; template <int N> static void k(decltype(lambda{}())); template <int N> static void k(decltype(lambda{}())); // okay today template <int N> static void k(int); // okay today
同样的论点也适用于 OP 的示例,并且(可以说)“行为与此等效,无需任何特殊措辞”:
struct lambda { auto operator()() const { struct S{}; return S{}; } };
using T = decltype(lambda{});
[[maybe_unused]] constexpr auto N = sizeof( []{ struct S{}; return S{}; } );
请注意,sizeof
更简单,因为您正在查询无捕获 lambda 的闭包类型的大小,而不是本地 struct 的大小S
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句