C++ 将C++;0x支持“uu stdcall或extern”;";兰博达斯?

C++ 将C++;0x支持“uu stdcall或extern”;";兰博达斯?,c++,c,lambda,c++11,C++,C,Lambda,C++11,昨天我在考虑是否可以利用C++0x lambda函数的便利性为Windows API函数编写回调 例如,如果我想使用lambda作为with?比如: EnumChildWindows(hTrayWnd, CALLBACK [](HWND hWnd, LPARAM lParam) { // ... return static_cast<BOOL>(TRUE); // continue enumerating }, reinterpret_cast

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

例如,如果我想使用lambda作为with?比如:

EnumChildWindows(hTrayWnd, CALLBACK [](HWND hWnd, LPARAM lParam) {
        // ...
        return static_cast<BOOL>(TRUE); // continue enumerating
    }, reinterpret_cast<LPARAM>(&myData));
这可能吗

我可以理解,捕获变量的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) { /* ... */ });
}
5.1.2/6
中的FCD措辞:

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


我认为最终的标准应该有一个注释,即C函数指针和C++链接指针都有转换函数,因为C函数指针的可兑换性是这个功能的目标之一。

< P>没有特别好的理由,不应该扩展到捕获lambda。它需要一些动态代码生成,但这不应该超出编译器编写人员的能力,而且它将使与旧C API的互操作变得更容易——不再需要通过非类型化的void*s传递参数(并非所有API都提供).

C++11标准中未规定无捕获lambda转换产生的函数指针的语言链接,但其中说明:

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

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

不带lambda捕获的lambda表达式的闭包类型有一个公共非虚拟非显式转换函数,用C++语言链接(7.5 [dCL,链接])指向函数指针。与闭包类型的函数调用运算符具有相同的参数和返回类型。返回的值


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

问题不是动态代码生成,而是动态代码清理。你必须有语言级的GC来清理代码,这比C++中的其他任何东西都要多。共享一个thunk就足够了。这在针对C++11标准的缺陷报告中得到了澄清,正如我在下面的回答中所解释的。很好的发现。但是,如果这是一个在C++11生命周期内提出并被接受的缺陷,那么这肯定意味着它确实适用于C++11?@下划线\d如果我们看一下定义术语(如
DRWP
)的是:
一个DR问题,其解决方案反映在当前的工作文件中。工作文件是标准未来版本的草案。
据我所知,这意味着它适用于C++14而不是C++11。
typedef void(*callbackType)(void *userData);
extern "C" void someCFunction(callbackType callback);

int main() {
  someCFunction([](void *userData) { /* ... */ });
}