{"id":44623,"date":"2015-02-20T07:00:00","date_gmt":"2015-02-20T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2015\/02\/20\/non-capturing-c-lambdas-can-be-converted-to-a-pointer-to-function-but-what-about-the-calling-convention\/"},"modified":"2019-03-13T12:13:08","modified_gmt":"2019-03-13T19:13:08","slug":"20150220-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20150220-00\/?p=44623","title":{"rendered":"Non-capturing C++ lambdas can be converted to a pointer to function, but what about the calling convention?"},"content":{"rendered":"<p>First, let&#8217;s look at how lambdas are implemented in C++. <\/p>\n<p>It is similar in flavor to <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2006\/08\/02\/686456.aspx\">the way lambdas are implemented in C#<\/a>, but the details are all different. <\/p>\n<p>When the C++ compiler encounters a lambda expression, it generates a new anonymous class. Each captured variable becomes a member of that anonymous class, and the member is initialized from the variable in the outer scope. Finally, the anonymous class is given an <code>operator()<\/code> implementation whose parameter list is the parameter list of the lambda, whose body is the lambda body, and whose return value is the lambda return value. <\/p>\n<p>I am simplifying here. You can read the C++ language specification for gory details. The purpose of this discussion is just to give a conceptual model for how lambdas work so we can get to answering the question. The language also provides for syntactic sugar to infer the lambda return type and capture variables implicitly. Let&#8217;s assume all the sugar has been applied so that everything is explicit. <\/p>\n<p>Here&#8217;s a basic example: <\/p>\n<pre>\nvoid ContainingClass::SomeMethod()\n{\n int i = 0, j = 1;\n auto f = [this, i, &amp;j](int k) -&gt; int\n    { return this-&gt;calc(i + j + k); };\n ...\n}\n<\/pre>\n<p>The compiler internally converts this to something like this: <\/p>\n<pre>\nvoid ContainingClass::SomeMethod()\n{\n int i = 0, j = 1;\n\n \/\/ Autogenerated by the compiler\n <font COLOR=\"blue\">class AnonymousClass$0\n {\n public:\n  AnonymousClass$0(ContainingClass* this$, int i$, int&amp; j$) :\n   this$0(this$), i$0(i$), j$0(j$) { }\n  int operator<\/font>(int k) <font COLOR=\"blue\">const<\/font>\n     { return this$0-&gt;calc(i$0 + j$0 + k); }\n <font COLOR=\"blue\">private:\n  ContainingClass* this$0; \/\/ this captured by value\n  int i$0;                 \/\/ i captured by value\n  int&amp; j$0;                \/\/ j captured by reference\n };<\/font>\n\n auto f = <font COLOR=\"blue\">AnonymousClass$0<\/font>(this, i, j);\n ...\n}\n<\/pre>\n<p>We are closer to answering the original question. but we&#8217;re not there yet. <\/p>\n<p>As a special bonus: If there are no captured variables, then there is an additional conversion operator that can convert the lambda to a pointer to a nonmember function. This is possible only in the case of no captured variables because captured variables would require an <code>AnonymousClass$0<\/code> instance parameter, but there is nowhere to pass it. <\/p>\n<p>Here&#8217;s a lambda with no captured variables. <\/p>\n<pre>\nvoid ContainingClass::SomeMethod()\n{\n auto f = [](int k) -&gt; int { return calc(k + 42); };\n ...\n}\n<\/pre>\n<p>The above code gets transformed to <\/p>\n<pre>\nvoid ContainingClass::SomeMethod()\n{\n class AnonymousClass$0\n {\n public:\n  AnonymousClass$0()  { }\n  <font COLOR=\"blue\">operator int (*)(int k) { return static_function; }<\/font>\n  int operator(int k) <font COLOR=\"blue\">const<\/font> { return calc(k + 42); }\n private:\n  static int static_function(int k) { return calc(k + 42); }\n };\n\n auto f = AnonymousClass$0();\n ...\n}\n<\/pre>\n<p>Okay, now we can get to the actual question: How can I specify <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2014\/01\/27\/10492898.aspx#10493271\">the calling convention for this implicit conversion to a pointer to nonmember function<\/a>? <\/p>\n<p>(Note that calling conventions are not part of the C++ standard, so this question is necessarily a platform-specific question.) <\/p>\n<p>The Visual C++ compiler automatically <a HREF=\"http:\/\/blogs.msdn.com\/b\/vcblog\/archive\/2011\/09\/12\/10209291.aspx\">provides conversions for every calling convention<\/a>. So with Visual C++, the transformed code actually looks like this: <\/p>\n<pre>\nvoid ContainingClass::SomeMethod()\n{\n class AnonymousClass$0\n {\n public:\n  AnonymousClass$0()  { }\n  <font COLOR=\"blue\">operator int (__cdecl *)(int k) { return cdecl_static_function; }\n  operator int (__stdcall *)(int k) { return stdcall_static_function; }\n  operator int (__fastcall *)(int k) { return fastcall_static_function; }<\/font>\n  int operator(int k) { return cdecl_static_function(k); }\n private:\n  static int __cdecl cdecl_static_function(int k) { return calc(k + 42); }\n  static int __stdcall stdcall_static_function(int k) { return calc(k + 42); }\n  static int __fastcall fastcall_static_function(int k) { return calc(k + 42); }\n };\n\n auto f = AnonymousClass$0();\n ...\n}\n<\/pre>\n<p>In other words, the compiler creates all the conversions, just in case. (The versions you don&#8217;t use will be removed by the linker.) <\/p>\n<p>But only for noncapturing lambdas. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nothing to see, so nothing to pass.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-44623","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Nothing to see, so nothing to pass.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=44623"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44623\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=44623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=44623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=44623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}