C ++ 0x是否支持__stdcall或extern“C”capture-nothing lambdas?

昨天我在考虑是否可以使用C ++ 0x lambda函数的便利来编写Windows API函数的回调。

例如,如果我想将一个lambda用作EnumChildProcEnumChildWindows怎么办? 就像是:

 EnumChildWindows(hTrayWnd, CALLBACK [](HWND hWnd, LPARAM lParam) { // ... return static_cast(TRUE); // continue enumerating }, reinterpret_cast(&myData)); 

另一个用途是为C例程编写extern "C"回调。 例如:

 my_class *pRes = static_cast(bsearch(&key, myClassObjectsArr, myClassObjectsArr_size, sizeof(my_class), extern "C" [](const void *pV1, const void *pV2) { const my_class& o1 = *static_cast(pV1); const my_class& o2 = *static_cast(pV2); int res; // ... return res; })); 

这可能吗?

我可以理解,捕获变量的lambda将永远不会与C兼容,但至少对我来说似乎可以捕获 – 没有任何 lambda可以兼容。

没有捕获的Lambda 可以隐式转换为指向函数的指针(通过闭包类型定义的非显式转换函数)。

FCD似乎没有指定该函数指针类型的函数类型具有哪种语言链接,因此如果需要将此函数指针传递给C函数,则C ++函数和C函数的调用约定必须相同。 我相信在Windows上,情况确实如此。 所以你应该能够将lambda传递给Windows API函数

 typedef void(*callbackType)(void *userData); extern "C" void someCFunction(callbackType callback); int main() { someCFunction([](void *userData) { /* ... */ }); } 

FCD措辞见5.1.2/6

没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数。 此转换函数返回的值应为函数的地址,该函数在调用时具有与调用闭包类型的函数调用运算符相同的效果。

我认为最终的标准应该有一个说明,即C语言链接函数指针和C ++链接函数指针都有转换函数,因为转换为C函数指针是此function的目标之一。

没有特别好的理由不应该将其扩展到捕获lambda。 它需要一些动态代码生成,但它不应该超出编译器编写者的作用,并且它将使旧C API的数量级更容易互操作 – 不再需要通过无类型的void * s传递参数(并非所有API甚至提供)。

函数指针的语言链接来自于无捕获lambda的转换,未在C ++ 11标准中指定,但在缺陷报告1557中解决了该问题:

5.1.2 [expr.prim.lambda]第6段没有指定闭包类型转换函数的函数类型的语言链接。

解决方案是语言链接应该是C ++:

没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有C ++语言链接的函数(7.5 [dcl.link])。 具有与闭包类型的函数调用操作符相同的参数和返回类型。 返回的值…

我们可以在C ++ 14标准草案中找到这种语言,因为状态是DRWP ,似乎这不适用于C ++ 11。