Obtaining function pointer to lambda?

前端 未结 3 1178
野的像风
野的像风 2020-12-23 16:35

I want to be able to obtain a function pointer to a lambda in C++.

I can do:

int (*c)(int) = [](int i) { return i; };

And, of cours

相关标签:
3条回答
  • 2020-12-23 17:17

    This fails:

    auto *b = [](int i) { return i; };
    

    because the lambda is not a pointer. auto does not allow for conversions. Even though the lambda is convertible to something that is a pointer, that's not going to be done for you - you have to do it yourself. Whether with a cast:

    auto *c = static_cast<int(*)(int)>([](int i){return i;});
    

    Or with some sorcery:

    auto *d = +[](int i) { return i; };
    
    0 讨论(0)
  • 2020-12-23 17:30

    Especially when it can implicitly convert a unique, lambda type to a function pointer:

    But it cannot convert it to "a function pointer". It can only convert it to a pointer to a specific function signature. This will fail:

    int (*h)(float) = a;
    

    Why does that fail? Because there is no valid implicit conversion from a to h here.

    The conversion for lambdas is not compiler magic. The standard simply says that the lambda closure type, for non-capturing, non-generic lambdas, has an implicit conversion operator for function pointers matching the signature of its operator() overload. The rules for initializing int (*g)(int) from a permit using implicit conversions, and thus the compiler will invoke that operator.

    auto doesn't permit using implicit conversion operators; it takes the type as-is (removing references, of course). auto* doesn't do implicit conversions either. So why would it invoke an implicit conversion for a lambda closure and not for a user-defined type?

    0 讨论(0)
  • 2020-12-23 17:32

    The lambda code doesn't work for the same reason this doesn't work:

    struct foo {
      operator int*() const {
        static int x;
        return &x;
      }
    };
    
    int* pint = foo{};
    auto* pint2 = foo{}; // does not compile
    

    or even:

    template<class T>
    void test(T*) {};
    test(foo{});
    

    The lambda has an operator that implicitly converts it to a (particular) function pointer, just like foo.

    auto does not do conversion. Ever. Auto behaves like a class T parameter to a template function where its type is deduced.

    As the type on the right hand side is not a pointer, it cannot be used to initialize an auto* variable.

    Lambdas are not function pointers. Lambdas are not std::functions. They are auto-written function objects (objects with an operator()).

    Examine this:

    void (*ptr)(int) = [](auto x){std::cout << x;};
    ptr(7);
    

    it compiles and works in gcc (not certain if it is an extension, now that I think about it). However, what would auto* ptr = [](auto x){std::cout << x;} supposed to do?

    However, unary + is an operator that works on pointers (and does nearly nothing to them), but not in foo or a lambda.

    So

    auto* pauto=+foo{};
    

    And

    auto* pfun=+[](int x){};
    

    Both work, magically.

    0 讨论(0)
提交回复
热议问题