C++ lambda函子到函数指针的编译时转换
正如我们所知,非捕获lambda函子可以在运行时转换为函数指针,但编译时又如何呢?也就是说,是否可能出现类似于下面代码的情况?请不要建议解决方法,比如将lambda函子作为函数参数传递,我想知道更多C++11标准禁止的地方/方式C++ lambda函子到函数指针的编译时转换,c++,c++11,C++,C++11,正如我们所知,非捕获lambda函子可以在运行时转换为函数指针,但编译时又如何呢?也就是说,是否可能出现类似于下面代码的情况?请不要建议解决方法,比如将lambda函子作为函数参数传递,我想知道更多C++11标准禁止的地方/方式 template <void(*fptr)()> void f() { // do something } int main() { auto l([]{}); f<(void(*)())(decltype(l))>();
template <void(*fptr)()>
void f()
{
// do something
}
int main()
{
auto l([]{});
f<(void(*)())(decltype(l))>();
return 0;
}
Lambda表达式,即使带有空闭包,也不能用作指向函数模板参数的指针,因为它们是临时表达式,恰好转换为指向函数的指针。根据5.1.2[expr.prim.lambda]第2段,lambda表达式为临时表达式: 对lambda表达式的求值会产生一个临时值。[……] 第6段描述了向函数指针的转换: 没有lambda捕获的lambda表达式的闭包类型具有一个公共非虚拟非显式const转换函数,该函数指向与闭包类型的函数调用运算符具有相同参数和返回类型的函数指针。此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果 也就是说,转换不会产生
constepr
,因此,不希望将结果函数指针用作模板参数
至于我现在能找到的最好的理由是一份声明,其中的观点似乎在谈论实际问题,但我找不到详细的讨论。似乎lambda表达式创建的函数的名称混乱是禁止在某些上下文中使用它们的问题之一。[expr.prim.lambda]/6“没有lambda捕获的非泛型lambda表达式的闭包类型具有一个公共的非虚拟非显式const转换函数到指向函数[…]的指针。”而且它不需要是
constexpr
@DyP aaah,运行时操作符有故障。请粘贴作为答案。如果我知道为什么不要求它是constexpr
,那么可能;)备注:1)常量表达式中不允许出现重新解释\u cast
;C样式转换(类型)表达式可以解析为重新解释转换。2) decltype
生成一个类型,并且不能将类型转换为值。您的函数模板f
采用非类型模板参数,因此该参数应为f()
,或f()
@DyP-Yeah,无论什么都可以。我没有粘贴一个工作示例。尽管如此,它说C风格的转换可以被解析为一个重新解释的转换
,而不是说它必须被解析。
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))>();
^