获取lambda的函数指针?

时间:2016-06-08 18:10:21

标签: c++ c++11 lambda c++14

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

我能做到:

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

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

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

但是以下内容:

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

在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)>'

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

int (*g)(int) = a;

我在http://coliru.stacked-crooked.com/a/2cbd62c8179dc61b创建了一个包含上述示例的小型试验台。在C ++ 11和C ++ 14下,这种行为是相同的。

3 个答案:

答案 0 :(得分:44)

这失败了:

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

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

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

some sorcery

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

答案 1 :(得分:7)

  

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

但它无法将其转换为&#34;函数指针&#34;。它只能将其转换为指向特定函数签名的指针。这将失败:

int (*h)(float) = a;

为什么会失败?因为此处没有从ah的有效隐式转换。

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

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

答案 2 :(得分:5)

lambda代码无法正常工作,原因与此无关:

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

int* pint = foo{};
auto* pint2 = foo{}; // does not compile

甚至:

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

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

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

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

Lambda不是函数指针。 Lambda不是std::function。它们是自动编写的函数对象(具有operator()的对象)。

检查一下:

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

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

但是,一元+是一个处理指针的运算符(对它们几乎没有任何作用),但不在foo或lambda中。

所以

auto* pauto=+foo{};

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

两者都是神奇地工作。