将lambda仿函数编译时转换为函数指针

时间:2013-09-07 11:52:24

标签: c++ c++11

众所周知,非捕获lambda仿函数可以在运行时转换为函数指针,但编译时间如何呢?也就是说,类似于下面的代码可能吗?请不要建议一个解决方法,比如将lambda仿函数作为函数参数传递,我想知道更多C ++ 11标准在哪里/如何禁止它。

template <void(*fptr)()>
void f()
{
  // do something
}

int main()
{
  auto l([]{});

  f<(void(*)())(decltype(l))>();

  return 0;
}

gcc-4.8的强制性错误:

c.cpp: In function 'int main()':
c.cpp:11:7: error: parse error in template argument list
       f<(void(*)())(decltype(l))>();
       ^
c.cpp:11:36: error: statement cannot resolve address of overloaded function
       f<(void(*)())(decltype(l))>();
                                    ^

1 个答案:

答案 0 :(得分:2)

Lambda表达式,即使是一个空的闭包,也可以用作指向函数模板参数的指针,因为它们恰好是转换为某个指向函数的指针。根据5.1.2 [expr.prim.lambda]第2段:

,lambda表达式是临时的
  

lambda表达式的评估会导致prvalue临时。 [...]

第6段中描述了转换为指向功能的指针:

  

没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数。此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用操作符具有相同的效果。

也就是说,转换不会产生constexpr,因此,没有希望使用结果指针作为模板参数。

至于我现在能找到的最好的原因是N3597中的一个声明,它指向N2895,似乎在谈论实际问题,但我找不到详细的讨论。似乎lambda表达式创建的函数的名称修改是禁止在某些上下文中使用它们的问题之一。