获取lambda的函数指针?

oco*_*or0 36 c++ lambda c++11 c++14

我希望能够在C++中获得一个指向lambda的函数指针.

我可以:

int (*c)(int) = [](int i) { return i; };
Run Code Online (Sandbox Code Playgroud)

当然,以下工作 - 即使它没有创建函数指针.

auto a = [](int i) { return i; };
Run Code Online (Sandbox Code Playgroud)

但是以下内容:

auto *b = [](int i) { return i; };
Run Code Online (Sandbox Code Playgroud)

在GCC中给出了这个错误:

main.cpp: In function 'int main()':
main.cpp:13:37: error: unable to deduce 'auto*' from '<lambda closure object>main()::<lambda(int)>{}'
     auto *b = [](int i) { return i; };
                                      ^
main.cpp:13:37: note:   mismatched types 'auto*' and 'main()::<lambda(int)>'
Run Code Online (Sandbox Code Playgroud)

似乎任意一个lambda可以毫无问题地转换为函数指针,但是编译器无法推断函数类型并使用它来创建指向它的指针auto *.特别是当它可以隐式转换unique, lambda type为函数指针时:

int (*g)(int) = a;
Run Code Online (Sandbox Code Playgroud)

我在http://coliru.stacked-crooked.com/a/2cbd62c8179dc61b上创建了一个小测试床,其中包含上述示例.在C++ 11和C++ 14下,此行为是相同的.

Bar*_*rry 46

这失败了:

auto *b = [](int i) { return i; };
Run Code Online (Sandbox Code Playgroud)

因为lambda不是指针.auto不允许转换.即使lambda 可以转换为指针,也不会为你做 - 你必须自己做.是否有演员表:

auto *c = static_cast<int(*)(int)>([](int i){return i;});
Run Code Online (Sandbox Code Playgroud)

或者用一些巫术:

auto *d = +[](int i) { return i; };
Run Code Online (Sandbox Code Playgroud)

  • @ Jaa-c只是不要'auto*d = ++ [](int i){return i; ` - 一个一元加太多! (7认同)
  • 这是做什么的?从来没有见过这种`+`语法. (6认同)
  • 谢谢 - 现在我必须至少使用一次.评论家会恨我. (4认同)
  • 加上1 +,我忘记了. (4认同)
  • 请注意,"+"至少在某些MSVC上失败.因为他们的lambdas有四个转换操作符来实现指针:/ (3认同)

Nic*_*las 8

特别是当它可以隐式地将唯一的lambda类型转换为函数指针时:

但它无法将其转换为"函数指针".它只能将其转换为指向特定函数签名的指针.这将失败:

int (*h)(float) = a;
Run Code Online (Sandbox Code Playgroud)

为什么会失败?因为从没有有效的隐式转换ah这里.

lambdas的转换不是编译魔术.该标准简单地说,对于非捕获的非泛型lambda,lambda闭包类型具有与其operator()重载的签名匹配的函数指针的隐式转换运算符.使用隐式转换int (*g)(int)apermit 初始化的规则,因此编译器将调用该运算符.

auto不允许使用隐式转换运算符; 它采用类型原样(当然,删除引用).auto*也不进行隐式转换.那么为什么它会调用lambda闭包的隐式转换而不是用户定义的类型呢?


Yak*_*ont 5

lambda代码不起作用的原因与此不起作用:

struct foo {
  operator int*() const {
    static int x;
    return &x;
  }
};

int* pint = foo{};
auto* pint2 = foo{}; // does not compile
Run Code Online (Sandbox Code Playgroud)

甚至:

template<class T>
void test(T*) {};
test(foo{});
Run Code Online (Sandbox Code Playgroud)

lambda有一个运算符,它隐式地将它转换为(特定)函数指针,就像foo.

auto不进行转换.永远.自动行为类似于class T模板函数的参数,其中推导出其类型.

由于右侧的类型不是指针,因此不能用于初始化auto*变量.

Lambda不是函数指针.兰巴达不是std::function.它们是自动编写的函数对象(带有a的对象operator()).

检查一下:

void (*ptr)(int) = [](auto x){std::cout << x;};
ptr(7);
Run Code Online (Sandbox Code Playgroud)

它编译并在gcc中工作(不确定它是否是扩展,现在我考虑它).但是,该怎么auto* ptr = [](auto x){std::cout << x;}办呢?

但是,unary +是一个运算符,它可以处理指针(并且对它们几乎没有任何作用),但不是foo或者是lambda.

所以

auto* pauto=+foo{};
Run Code Online (Sandbox Code Playgroud)

auto* pfun=+[](int x){};
Run Code Online (Sandbox Code Playgroud)

两者都神奇地工作.