std :: function绑定到成员函数 [英] std::function bound to member function
问题描述
以下代码不在VS2012中编译
class Zot
{
public:
int A(){return 123; }
};
int _tmain(int argc,_TCHAR * argv [])
{
std :: function< int(Zot *)> fn =& Zot :: A;
return 0;
}
但是,将作业更改为
std :: function< int(Zot *)> fn = std :: bind(& Zot :: A,std :: placeholders :: _ 1);
有效。
很多在线示例显示原始语法。
有一个有效的简短格式的作业吗?
编辑:编译器错误(为可执行性稍作编辑)为:
1> ; vc \include\functional(515):error C2664:'std :: _ Func_class< _Ret,_V0_t> :: _set':不能将参数1从'_Myimpl *'转换为'std :: _ Func_base< _Rx,_V0_t& *'
include
1> with
1> [
1> _Ret = int,
1> _V0_t = Zot *
1> ]
1>和
1> [
1> _Rx = int,
1> _V0_t = Zot *
1> ]
1>指向的类型是不相关的;转换需要reinterpret_cast,C风格的转换或函数式转换
1> vc \include\functional(515):参见函数模板实例化的参考'void std :: _ Func_class< _Ret,_V0_t> :: Do_alloc< _Myimpl,_Fret(__ thiscall Zot :: * const&)(void),_ Alloc> ;(_ Fty,_Alloc)'正在编译
1> with
1> [
1> _Ret = int,
1> _V0_t = Zot *,
1> _Fret = int,
1> _Alloc = std :: allocator< std :: _ Func_class< int,Zot *>>,
1> _Fty = int(__thiscall Zot :: * const&)(void)
1> ]
1> vc \include\functional(515):参见函数模板实例化的参考'void std :: _ Func_class< _Ret,_V0_t> :: Do_alloc< _Myimpl,_Fret(__ thiscall Zot :: * const&)(void),_ Alloc> ;(_ Fty,_Alloc)'正在编译
1> with
1> [
1> _Ret = int,
1> _V0_t = Zot *,
1> _Fret = int,
1> _Alloc = std :: allocator< std :: _ Func_class< int,Zot *>> ;,
1> _Fty = int(__thiscall Zot :: * const&)(void)
1> ]
1> vc \include\functional(515):参见对函数模板实例化的引用'void std :: _ Func_class< _Ret,_V0_t> :: Reset_alloc< _Fret,Zot,std :: allocator< _Ty> :: * const)(void),_ Alloc)'正在编译
1> with
1> [
1> _Ret = int,
1> _V0_t = Zot *,
1> _Fret = int,
1> _Ty = std :: _ Func_class< int,Zot *>,
1> _Alloc = std :: allocator< std :: _ Func_class< int,Zot *>>
1> ]
1> vc \include\functional(515):参见对函数模板实例化的引用'void std :: _ Func_class< _Ret,_V0_t> :: Reset_alloc< _Fret,Zot,std :: allocator< _Ty> :: * const)(void),_ Alloc)'正在编译
1> with
1> [
1> _Ret = int,
1> _V0_t = Zot *,
1> _Fret = int,
1> _Ty = std :: _ Func_class< int,Zot *>,
1> _Alloc = std :: allocator< std :: _ Func_class< int,Zot *>>
1> ]
1> vc \include\functional(675):参见对函数模板实例化的引用'void std :: _ Func_class< _Ret,_V0_t> :: _ Reset< int,Zot>(_Fret(__thiscall Zot :: * const) '正在编译
1> with
1> [
1> _Ret = int,
1> _V0_t = Zot *,
1> _Fret = int
1> ]
1> vc \include\functional(675):参见对函数模板实例化的引用'void std :: _ Func_class< _Ret,_V0_t> :: _ Reset< int,Zot>(_Fret(__thiscall Zot :: * const) '正在编译
1> with
1> [
1> _Ret = int,
1> _V0_t = Zot *,
1> _Fret = int
1> ]
1> c:\..\cxx11.cpp(17):参见对函数模板实例化的引用'std :: function< _Fty> :: function< int(__ thiscall Zot :: *)(void)> &)'正在编译
1> with
1> [
1> _Fty = int(Zot *),
1> _Fx = int(__thiscall Zot :: *)(void)
1> ]
1> c:\ ... \cxx11.cpp(17):参见函数模板实例的引用'std :: function< _Fty> :: function< int(__ thiscall Zot :: *)(void)> ;&)'正在编译
1> with
1> [
1> _Fty = int(Zot *),
1> _Fx = int(__thiscall Zot :: *)(void)
1> ]
是的,它应该可以工作( demo )。对于任何适当的构造函数(例如
template< class F> function(F f);
)的函数参数的要求之一是std: :function< R(ArgsTypes ...)>
是:
$ b (20.8.11.2)的参数类型
ArgTypes
和返回类型R
$ b(20.8.11.2.1 functionconstruct / copy / destroy [func.wrap.func.con])
依次为参数类型
ArgTypes
和返回类型R
是根据伪表达式INVOKE(f,declat
定义的标准准概念(由于缺少概念)。这个伪表达式使用通常的调用语法(例如()...,R) f(a,b,c)
)调用常规函子,指针指向具有自己的怪癖(例如p-> * a
或(r。* a)(b,c)
)。
此外,使用<$ c $的调用运算符的效果c> std :: function
INVOKE(f,std :: forward< ArgTypes>(args)...,R)
(20.8。 11.2.4函数调用[func.wrap.func.inv]),意味着对成员的指针执行正确事情。
事实上,很多在标准中也按照 Callable / > INVOKE 定义的其他东西,例如
std :: bind
,std :: thread
,std :: reference_wrapper
和std :: result_of
*。
*:特别是这意味着像
template< typename Functor>
typename std :: result_of< Functor()> :: type apply(Functor functor)
{return std :: forward< Functor>(functor) }
是有问题的,至少因为这个原因。
The following code doesn't compile in VS2012
class Zot { public: int A() { return 123; } }; int _tmain(int argc, _TCHAR* argv[]) { std::function<int (Zot*)> fn = &Zot::A; return 0; }
However, changing the assignment to
std::function<int (Zot*)> fn = std::bind(&Zot::A, std::placeholders::_1);
Does work.
There are a lot of online examples that show the original syntax. Did something change in the C++11 spec to disallow this syntax?
Is there a valid shorter form for the assignment?
Edit: the compiler error (slightly edited for reabability) is:
1>vc\include\functional(515): error C2664: 'std::_Func_class<_Ret,_V0_t>::_Set' : cannot convert parameter 1 from '_Myimpl *' to 'std::_Func_base<_Rx,_V0_t> *' 1> with 1> [ 1> _Ret=int, 1> _V0_t=Zot * 1> ] 1> and 1> [ 1> _Rx=int, 1> _V0_t=Zot * 1> ] 1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 1> vc\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Do_alloc<_Myimpl,_Fret(__thiscall Zot::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled 1> with 1> [ 1> _Ret=int, 1> _V0_t=Zot *, 1> _Fret=int, 1> _Alloc=std::allocator<std::_Func_class<int,Zot *>>, 1> _Fty=int (__thiscall Zot::* const &)(void) 1> ] 1> vc\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Do_alloc<_Myimpl,_Fret(__thiscall Zot::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled 1> with 1> [ 1> _Ret=int, 1> _V0_t=Zot *, 1> _Fret=int, 1> _Alloc=std::allocator<std::_Func_class<int,Zot *>>, 1> _Fty=int (__thiscall Zot::* const &)(void) 1> ] 1> vc\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset_alloc<_Fret,Zot,std::allocator<_Ty>>(_Fret (__thiscall Zot::* const )(void),_Alloc)' being compiled 1> with 1> [ 1> _Ret=int, 1> _V0_t=Zot *, 1> _Fret=int, 1> _Ty=std::_Func_class<int,Zot *>, 1> _Alloc=std::allocator<std::_Func_class<int,Zot *>> 1> ] 1> vc\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset_alloc<_Fret,Zot,std::allocator<_Ty>>(_Fret (__thiscall Zot::* const )(void),_Alloc)' being compiled 1> with 1> [ 1> _Ret=int, 1> _V0_t=Zot *, 1> _Fret=int, 1> _Ty=std::_Func_class<int,Zot *>, 1> _Alloc=std::allocator<std::_Func_class<int,Zot *>> 1> ] 1> vc\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset<int,Zot>(_Fret (__thiscall Zot::* const )(void))' being compiled 1> with 1> [ 1> _Ret=int, 1> _V0_t=Zot *, 1> _Fret=int 1> ] 1> vc\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset<int,Zot>(_Fret (__thiscall Zot::* const )(void))' being compiled 1> with 1> [ 1> _Ret=int, 1> _V0_t=Zot *, 1> _Fret=int 1> ] 1> c:\..\cxx11.cpp(17) : see reference to function template instantiation 'std::function<_Fty>::function<int(__thiscall Zot::* )(void)>(_Fx &&)' being compiled 1> with 1> [ 1> _Fty=int (Zot *), 1> _Fx=int (__thiscall Zot::* )(void) 1> ] 1> c:\...\cxx11.cpp(17) : see reference to function template instantiation 'std::function<_Fty>::function<int(__thiscall Zot::* )(void)>(_Fx &&)' being compiled 1> with 1> [ 1> _Fty=int (Zot *), 1> _Fx=int (__thiscall Zot::* )(void) 1> ]
解决方案Yes, it should work (demo). One of the requirements on the functor argument for any of the appropriate constructor (e.g.
template<class F> function(F f);
) ofstd::function<R(ArgsTypes...)>
is:f shall be Callable (20.8.11.2) for argument types
ArgTypes
and return typeR
.(20.8.11.2.1 functionconstruct/copy/destroy [func.wrap.func.con])
In turn, "Callable for argument types
ArgTypes
and return typeR
" is a Standard quasi-concept (for lack of concepts) defined in terms of the pseudo-expressionINVOKE(f, declval<ArgTypes>()..., R)
. This pseudo-expression unifies regular functors, which are invoked with the usual call syntax (e.g.f(a, b, c)
), with pointers to members which have their own quirks (e.g.p->*a
or(r.*a)(b, c)
). INVOKE is defined in 20.8.2 Requirements [func.require].Furthermore, the effects of using the call operator of
std::function
includeINVOKE(f, std::forward<ArgTypes>(args)..., R)
(20.8.11.2.4 function invocation [func.wrap.func.inv]), meaning that the 'right' thing is done for pointers to members.There are in fact a lot of other things that are also defined in terms of Callable/INVOKE in the Standard, like
std::bind
,std::thread
,std::reference_wrapper
andstd::result_of
*.*: in particular this means that something like
template<typename Functor> typename std::result_of<Functor()>::type apply(Functor functor) { return std::forward<Functor>(functor)(); }
is problematic at least for that reason.
这篇关于std :: function绑定到成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!