谁能帮我指出为什么这在 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-capture 的 lambda-expression 的闭包类型具有公共非虚拟非显式 const 转换函数,用于指向具有与闭包类型的函数调用相同的参数和返回类型的函数操作员。此转换函数返回的值应是函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果。
我如何告诉编译器他应该使用什么转换?
显然这是一个 VC++ bug。除了显式强制转换似乎没有其他方法:
+ 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;
}