C++ 标准是否保证无捕获lambda为空?

C++ 标准是否保证无捕获lambda为空?,c++,lambda,c++17,c++20,C++,Lambda,C++17,C++20,我正在寻找一种在模板函数中从其他lambda中识别空(无captureless)lambda的方法。我目前正在使用C++17,但我对C++20的答案也很好奇 我的代码如下所示: template<typename T> auto func(T lambda) { // The aguments of the lambdas are unknown if constexpr (/* is captureless */) { // do stuff

我正在寻找一种在模板函数中从其他lambda中识别空(无captureless)lambda的方法。我目前正在使用C++17,但我对C++20的答案也很好奇

我的代码如下所示:

template<typename T>
auto func(T lambda) {
    // The aguments of the lambdas are unknown

    if constexpr (/* is captureless */) {
        // do stuff
    }
}

不,事实上,该标准明确授予lambda不符合其声明的大小的权限。州

闭包类型在包含相应lambda表达式的最小块作用域、类作用域或命名空间作用域中声明。[注意:这将确定与闭包类型([basic.lookup.argdep])关联的名称空间和类的集合。lambda声明符的参数类型不会影响这些关联的名称空间和类。-结束注意]闭包类型不是聚合类型一个实现可能会定义不同于下面描述的闭包类型,前提是除了通过更改以下内容之外,不会改变程序的可观察行为:

  • 闭合类型的尺寸和/或对齐方式,

  • 闭包类型是可复制的([class.prop]),还是 (2.3)

  • 闭包类型是否为标准布局类([class.prop])

实现不应将右值引用类型的成员添加到闭包类型

重点矿山


因此,这允许实现为lambda提供一个成员,即使它的捕获更少。我不认为任何实现会这样做,但法律允许他们这样做。

如果你只关心非模板lambda,你可以使用SFINAE检查转换到函数指针(
+lambda
)的格式是否正确。@HolyBlackCat我考虑过,但据我记忆所及,MSVC不允许这样做,因为它们重载了转换运算符。@GuillaumeRacicot MS为所有可用的调用约定公开了一个单独的转换运算符。只需选择一个并尝试将lambda转换为可比较的函数指针,然后检查它是否成功。
+
似乎可以工作。
auto a = []{}; // captureless
auto b = [c = 'z']{}; // has captures

static_assert(sizeof(a) == sizeof(b)); // Both are the same size
static_assert(!std::is_empty_v<decltype(b)>); // It has a `c` member
static_assert(std::is_empty_v<decltype(a)>); // Passes. It is guaranteed?