可以在 C++20 的“decltype”或“sizeof”表达式中定义类型吗?
May types be defined in `decltype` or `sizeof` expressions in C++20?
由于 C++20 lambda 函数允许在未计算的上下文中使用,特别是它们应该允许在 decltype
和 sizeof
表达式中使用。
反过来,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
.
的大小
由于 C++20 lambda 函数允许在未计算的上下文中使用,特别是它们应该允许在 decltype
和 sizeof
表达式中使用。
反过来,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
.