std :: function绑定到成员函数

Rob*_*ker 6 c++ visual-c++ c++11 visual-c++-2012

以下代码无法在VS2012中编译

class Zot
{
public:
    int A() { return 123; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::function<int (Zot*)> fn = &Zot::A;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,将分配更改为

    std::function<int (Zot*)> fn = std::bind(&Zot::A, std::placeholders::_1);
Run Code Online (Sandbox Code Playgroud)

有用吗

有很多在线示例显示原始语法.在C++ 11规范中有什么变化来禁止这种语法吗?

是否有有效的简短表格?

编辑:编译器错误(为可重复性稍加编辑)是:

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>          ]
Run Code Online (Sandbox Code Playgroud)

Rob*_*ker 5

以下语法有效且至少更短:

std::function<int (Zot*)> fn = std::mem_fn(&Zot::A);
Run Code Online (Sandbox Code Playgroud)


Luc*_*ton 2

是的,它应该有效。template<class F> function(F f);对于任何适当的构造函数(例如),函子参数的要求之一std::function<R(ArgsTypes...)>是:

对于参数类型和返回类型,f 应是可调用的(20.8.11.2) 。ArgTypesR

(20.8.11.2.1 函数构造/复制/销毁 [func.wrap.func.con])

反过来,“可调用参数类型ArgTypes和返回类型R”是根据伪表达式定义的标准准概念(由于缺乏概念)INVOKE(f, declval<ArgTypes>()..., R)。这个伪表达式将常规函子(使用通常的调用语法(例如 )调用f(a, b, c))与指向具有自己的怪癖的成员的指针(例如p->*a(r.*a)(b, c))统一起来。INVOKE在 20.8.2 要求 [func.require] 中定义。

std::function此外,使用include (20.8.11.2.4 函数调用 [func.wrap.func.inv])的调用运算符的效果INVOKE(f, std::forward<ArgTypes>(args)..., R),意味着对指向成员的指针做了“正确”的事情。

事实上,标准中还根据Callable / INVOKE定义了很多其他内容,例如std::bindstd::threadstd::reference_wrapper* std::result_of

*:特别是这意味着类似

template<typename Functor>
typename std::result_of<Functor()>::type apply(Functor functor)
{ return std::forward<Functor>(functor)(); }
Run Code Online (Sandbox Code Playgroud)

至少由于这个原因是有问题的。