不同的 Lambda 可以衰减到同一个函数指针吗?

Ben*_*Ben 27 c++ lambda language-lawyer c++11

两个不同的 lambda(没有捕获,并且具有相同的参数和主体)可以衰减到相同的函数指针吗?

我有这个代码:

#include <cassert>
#include <type_traits>

int main() {
    auto f0 = [](auto x) { return x; };
    auto f1 = [](auto x) { return x; };
    
    static_assert(not std::is_same_v<decltype(f0), decltype(f1)>);

    // MSVC Release-mode combines the functions so the pointers are the same (even though the types should be different.
    assert(static_cast<int(*)(int)>(f0) != static_cast<int(*)(int)>(f1));
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/P3vc45654

我相信static_assert一定会通过。这样就assert保证能通过吗?(我看到 MSVC 在发布模式下assert在我的计算机上失败。)

Jer*_*fin 26

我不得不不同意现有的答案。

您没有使用函数调用运算符。您正在使用“函数指针”的转换。由于您的 lambda 表达式具有auto参数,因此它们是通用 lambda 表达式。

在这种情况下,到“函数指针”的转换描述如下(N4950,[expr.prim.lambda.closure]/9):

对于没有 lambda 捕获的通用 lambda,闭包类型具有一个到函数指针的转换函数模板。转换函数模板具有与函数调用运算符模板相同的发明模板参数列表,并且指向函数的指针具有相同的参数类型。函数指针的返回类型的行为应类似于 decltype 说明符,表示相应函数调用运算符模板特化的返回类型。

这里没有提到创建指向唯一函数的指针或类似的内容。

微软的实现似乎并没有违反任何规则。

  • 我的想法完全正确。指针只需指向执行 lambda 操作的函数即可。如果两个 lambda 执行相同的操作,那么它们都可能指向同一个合成函数。 (5认同)
  • 请注意,Visual Studio 报告仅在运行时比较函数指针时才相同,“static_assert”仍然表示它们是不同的:https://gcc.godbolt.org/z/Mje1rKz6c 合法吗? (2认同)
  • @Fedor 太疯狂了!这对我来说感觉不太对劲,尽管考虑到 `constexpr` 和运行时之间的差异,我想也许它是兼容的?它与函数模板的行为相同:https://gcc.godbolt.org/z/17MqMzWzG (2认同)