可以在 C++20 的“decltype”或“sizeof”表达式中定义类型吗?

May types be defined in `decltype` or `sizeof` expressions in C++20?

由于 C++20 lambda 函数允许在未计算的上下文中使用,特别是它们应该允许在 decltypesizeof 表达式中使用。

反过来,lambda 可以在它们的主体中定义一些类型以及这些类型的可能 return 个对象,例如:

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 在这里有一个错误。特别是论文中的以下讨论与此相关:

Furthermore, some questions were raised on the Core reflector regarding redeclarations like this:

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

These should be valid redeclarations, since the lambda expressions are evaluated, and they neither contain a template parameter in their body nor are part of a full-expression that contains one. Hence, the lambda-expression does not need to appear in the signature of the function, and the behavior is equivalent to this, without requiring any special wording:

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 闭包类型的大小,而不是本地结构 S.

的大小