#include <functional> class X { public: template <typename T> explicit X(T t) { std::bind(&X::invoke<T>,this,t)(); } private: template <typename T> void invoke(T t) { t(); } }; class Y { public: void foo() { //... } }; int main() { Y y; X x(std::bind(&Y::foo,&y)); return 0; }
但它完成了错误.我不确定粘贴整个编译器输出是否合理,但一般情况下
vc11说:
error C2664: ‘void std::_Pmf_wrap::operator ()(_Farg0 &,_V0_t) const’ : cannot convert parameter 3 from ‘void’ to ‘std::_Bind,Y *,std::_Nil,std::_Nil>’ c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional 1152 1 ConsoleApplication1 (Microsoft Visual C++ Compiler Nov 2012 CTP)
和g:
Compilation finished with errors:
source.cpp: In instantiation of ‘X::X(T) [with T = std::_Bind(Y*)>]’:
source.cpp:28:33: required from here
source.cpp:8:9: error: no match for call to ‘(std::_Bind_helper(Y*)>),X* const,std::_Bind(Y*)>&>::type {aka std::_Bind(Y*)>)>(X*,std::_Bind(Y*)>)>}) ()’
有没有办法解决这个问题.保存主要思想对于我来说非常重要 – 可以用任何可调用对象(函数对象,函数指针或std :: bind()函数返回的调用包装器)实例化的类.
如果有人帮忙,我将不胜感激.
解决方法
您可能希望以这种方式解决它:
template <typename T> explicit X(T t) { std::bind(&X::invoke<T>,std::placeholders::_1)(t); // ^^^^^^^^^^^^^^^^^^^^^ ^ }
这也可以,但是你不会允许绑定的结果比参数t更长(否则,你将传递一个悬空引用来调用< T>()):
template <typename T> explicit X(T t) { std::bind(&X::invoke<T>,cref(t))(); // ^^^^^^^ }
更新:
上述解决方案是有助于实现您在示例中显示的内容的解决方法.但是,从评论中可以看出,您的用例可能大不相同(例如,传递绑定结果以供以后评估).
正如Maxim Yegorushkin在他的回答中正确指出的那样,概念上正确的解决方案在于使用诸如Boost的保护之类的结构.
如果您不想使用Boost,使用C 11的可变参数模板定义您自己的protect()函数非常容易:
// Imitates boost::protect,but with variadic templates and perfect forwarding namespace detail { template<typename F> struct protect { private: F _f; public: explicit protect(F f): _f(f) { } template<typename... Ts> auto operator () (Ts&&... args) -> decltype(_f(std::forward<Ts>(args)...)) { return _f(std::forward<Ts>(args)...); } }; } template<typename F> detail::protect<F> protect(F&& f) { return detail::protect<F>(std::forward<F>(f)); }
最终,这是你在课堂上使用它的方式,正如Maxim建议的那样:
class X { public: template <typename T> explicit X(T t) { auto pt = protect(t); std::bind(&X::invoke<decltype(pt)>,pt)(); } private: template <typename T> void invoke(T t) { t(); } };