简体   繁体   中英

lambda with conversion function to pointer to function with c++ linkage

C++ standard has a below statement:

The closure type for a non-generic lambda-expression with no lambda-capture whose constraints (if any) are satisfied has a conversion function to pointer to function with C++ language linkage (10.5) having the same parameter and return types as the closure type's function call operator.

To understand the statement much better, I used the cppinsights to see what the clang compiler says for the below function.

#include <iostream>

using test = void (*)(int);

int main()
{
    test t = [](int arg) { std::cout << arg << std::endl; };
}

cppinsights translates the function as:

#include <iostream>

using test = void (*)(int);

int main()
{

  class __lambda_7_11
  {
    public: inline void operator()(int arg) const
    {
      std::cout.operator<<(arg).operator<<(std::endl);
    }

    public: using retType_7_11 = void (*)(int);
    inline operator retType_7_11 () const
    {
      return __invoke;
    }

    private: static inline void __invoke(int arg)
    {
      std::cout.operator<<(arg).operator<<(std::endl);
    }


  } __lambda_7_11{};

  using FuncPtr_7 = test;
  FuncPtr_7 t = static_cast<void (*)(int)>(__lambda_7_11.operator __lambda_7_11::retType_7_11());
}

As usual, the compiler generates an anonymous class with operator() overloaded along with "conversion function to pointer to function" as specified by the standard.

What I don't understand is that why a "static __invoke" function is generated and the "conversion function" is internally calling "__invoke" (directly as a function pointer) without any parameter which is expected by "__invoke"?

Cppinsights is correct in what it does. It returns the function pointer iso calling the function.

It would have been more readable if it would been writen the following way:

inline operator retType_7_11 () const
{
  return &__invoke;
}

However, the & ain't required in this case.

What I don't understand is that why a static __invoke function is generated and the "conversion function" is internally calling __invoke (directly as a function pointer) without any parameter which is expected by __invoke ?

The conversion function does not "internally call" __invoke , it just returns __invoke , ie, a pointer to a static member function. Remember that the difference between static and non- static member functions is that the former is not bound to a specific instance of that class, and can hence be treated as ordinary function pointers, as opposed to pointers to members. Have a look at the following example:

struct Test {
   void f();
   static void g();
};

void (Test::*f)() = &Test::f; // pointer to instance-specific member fct.
void (*g)() = &Test::g; // ordinary function pointer
void (*h)() = Test::g; // no ampersand, this is implicitly a function pointer

The latter is what you intend the result of the conversion to be, and what cppinsights shows you is nothing but a technique to implement this conversion: as the lambda expression has an empty closure, the function object generated by the compiler has no state, and a member function of an object with no state can be a static member function that can bind to an ordinary function pointer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM