operator + on Lambda

operator + on Lambda

本文关键字:Lambda on operator      更新时间:2023-10-16

有人能帮我指出为什么这在VS2013中不起作用吗?

auto p = +[]() -> void { std::cout << "Hello, world!n"; };
p();
source_file.cpp(7) : error C2593: 'operator +' is ambiguous
    could be 'built-in C++ operator+(void (__cdecl *)(void))'
    or       'built-in C++ operator+(void (__stdcall *)(void))'
    or       'built-in C++ operator+(void (__fastcall *)(void))'
    or       'built-in C++ operator+(void (__vectorcall *)(void))'

这是强制转换lambda 的合法运算符

5.1.2 Lambda表达式[expr.prim.Lambda]

6没有lambda捕获的lambda表达式的闭包类型有一个公共的非虚拟非显式常量转换函数,该函数指向与闭包类型的函数调用运算符具有相同参数和返回类型的函数。这个转换函数返回的值应该是一个函数的地址,该函数在被调用时与调用闭包类型的函数调用运算符具有相同的效果。

我如何告诉编译器应该使用什么转换?

显然这是一个VC++错误。除了显式铸造之外,似乎没有其他方法:

+ static_cast< void(*)() >( []{} ); // Empty lamba without loss of generality

不幸的是,魔法就这样消失了。

我找到了解决问题的方法。我第一篇文章中的最初问题可以通过使用C-Cast来解决,在不使用一元+运算符的情况下,向编译器提示p应该是什么类型。

using ExplicitCast = void();
// valid but does not work in MSVC
auto fn = +[]() {};
// fix for MSVC
auto fn = (ExplicitCast*)[]() {};

不幸的是,当参数列表中的类型不匹配时,这并不能解决问题(如果类型是继承的,这是合法的)。我有一个函数,其中第一个参数与lambda中的第一个参数不同。例如:

class Foo {};
class Bar : public Foo {};
using ExplicitCast = void(Bar*);
using Function = void(Foo*);
static Function* func = nullptr;
int main()
{
    // does not work because the parameter list does not match
    // func = [](Bar*) -> void { };
    // func = +[](Bar*) -> void { };
    // does work because we first explicit cast to a function and then to the needed function.
    func = (Function*)(ExplicitCast*)[](Bar*) -> void { };
    Bar o;
    func(&o);
    return 0;
}