5

众所周知,非捕获 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))>();
                                    ^
4

1 回答 1

2

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

对 lambda 表达式的求值会产生一个临时的纯右值。[...]

第 6 段描述了到函数指针的转换:

没有 lambda-capture 的 lambda 表达式的闭包类型具有一个公共的非虚拟非显式 const 转换函数,该函数指向具有与闭包类型的函数调用运算符相同的参数和返回类型的函数的指针。这个转换函数的返回值应该是一个函数的地址,当被调用时,它与调用闭包类型的函数调用运算符具有相同的效果。

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

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

于 2013-12-22T21:36:11.013 回答