#include <functional>
int foo(void) {return 2;}
class bar {
public:
int operator() (void) {return 3;};
int something(int a) {return a;};
};
template <class C> auto func(C&& c) -> decltype(c()) { return c(); }
template <class C> int doit(C&& c) { return c();}
template <class C> void func_wrapper(C&& c) { func( std::bind(doit<C>, std::forward<C>(c)) ); }
int main(int argc, char* argv[])
{
// call with a function pointer
func(foo);
func_wrapper(foo); // error
// call with a member function
bar b;
func(b);
func_wrapper(b);
// call with a bind expression
func(std::bind(&bar::something, b, 42));
func_wrapper(std::bind(&bar::something, b, 42)); // error
// call with a lambda expression
func( [](void)->int {return 42;} );
func_wrapper( [](void)->int {return 42;} );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在C++头文件中遇到了编译错误:
functional:1137: error: invalid initialization of reference of type ‘int (&)()’ from expression of type ‘int (*)()’
functional:1137: error: conversion from ‘int’ to non-scalar type ‘std::_Bind<std::_Mem_fn<int (bar::*)(int)>(bar, int)>’ requested
func_wrapper(foo)应该执行func(doit(foo)).在实际代码中,它打包了要执行的线程的函数.func将由另一个线程执行该函数,它们介于两者之间以检查未处理的异常并进行清理.但是func_wrapper中的额外绑定搞砸了......
现在第二次看这个,我想我对你看到的第一个错误有一个合理的解释。
\n\n在这种情况下,查看完整的错误和导致该错误的模板实例化会更有帮助。例如,我的编译器(GCC 4.4)打印的错误以以下几行结尾:
\n\ntest.cpp:12: instantiated from \xe2\x80\x98decltype (c()) func(C&&) [with C = std::_Bind<int (*(int (*)()))(int (&)())>]\xe2\x80\x99\ntest.cpp:16: instantiated from \xe2\x80\x98void func_wrapper(C&&) [with C = int (&)()]\xe2\x80\x99\ntest.cpp:22: instantiated from here\n/usr/include/c++/4.4/tr1_impl/functional:1137: error: invalid initialization of reference of type \xe2\x80\x98int (&)()\xe2\x80\x99 from expression of type \xe2\x80\x98int (*)()\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n\n现在从下往上看,实际的错误消息似乎是正确的;编译器推导的类型不兼容。
\n\n第一个模板实例化 at清楚地显示了编译器从 中func_wrapper
的实际参数推导出来的类型。我个人期望 this 是一个函数指针,但实际上它是一个函数引用。foo
func_wrapper(foo)
第二个模板实例化几乎不可读。但是稍微搞了一下std::bind
,我了解到 GCC 为绑定函子打印的文本表示的格式大致是:
std::_Bind<RETURN-TYPE (*(BOUND-VALUE-TYPES))(TARGET-PARAMETER-TYPES)>\n
Run Code Online (Sandbox Code Playgroud)\n\n所以把它拆开:
\n\nstd::_Bind<int (*(int (*)()))(int (&)())>\n// Return type: int\n// Bound value types: int (*)()\n// Target parameter types: int (&)()\n
Run Code Online (Sandbox Code Playgroud)\n\n这就是不兼容类型开始的地方。显然,即使c
infunc_wrapper
是函数引用,但一旦传递给,它就会变成函数指针std::bind
,导致类型不兼容。对于它的价值来说,std::forward
在这种情况下根本不重要。
我在这里的推理是,std::bind
似乎只关心值,而不关心引用。在 C/C++ 中,不存在函数值这样的东西;只有引用和指针。因此,当函数引用被取消引用时,编译器只能给你一个有意义的函数指针。
您对此唯一的控制权是您的模板参数。您必须告诉编译器您从一开始就正在处理函数指针才能使其工作。无论如何,这可能就是你的想法。为此,请明确指定模板参数所需的类型C
:
func_wrapper<int (*)()>(foo);\n
Run Code Online (Sandbox Code Playgroud)\n\n或者更简短的解决方案,显式获取函数的地址:
\n\nfunc_wrapper(&foo); // with C = int (*)()\n
Run Code Online (Sandbox Code Playgroud)\n\n如果我发现第二个错误,我会回复你。:)
\n 归档时间: |
|
查看次数: |
2573 次 |
最近记录: |