【问题标题】:std::function bound to member functionstd::function 绑定到成员函数
【发布时间】:2012-08-22 02:54:46
【问题描述】:

以下代码在 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);

确实有效。

有很多在线示例显示了原始语法。 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>          ]

【问题讨论】:

  • 在 VS2010 和 GCC 4.7.1 上按预期编译和运行
  • Luc Danton 的分析在我看来是合理的:这看起来可能是一个错误,至少值得进一步调查。如果您愿意,请在Microsoft Connect 上打开一个错误并在此处发布一个链接,以便其他人可以找到它。同时,我建议使用std::mem_fn 作为解决方法。
  • 谢谢 -- 我已将错误报告提交为:connect.microsoft.com/VisualStudio/feedback/details/759806/…

标签: c++ visual-c++ c++11 visual-c++-2012


【解决方案1】:

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

std::function<int (Zot*)> fn = std::mem_fn(&Zot::A);

【讨论】:

  • 为什么 std::mem_fn(&amp;Zot::A) 有效但 &amp;Zot::A 无效。请解释一下。
【解决方案2】:

是的,它应该可以工作。 std::function&lt;R(ArgsTypes...)&gt; 的任何适当构造函数(例如 template&lt;class F&gt; function(F f);)的函子参数的要求之一是:

对于参数类型 ArgTypes 和返回类型 R

f 应该是 Callable (20.8.11.2)。

(20.8.11.2.1 functionconstruct/copy/destroy [func.wrap.func.con])

反过来,“Callable for argument types ArgTypes and return type R”是根据伪表达式@987654327定义的标准准概念(因为缺少概念) @。这个伪表达式统一了常规函子,这些函子使用通常的调用语法(例如f(a, b, c))调用,并带有指向具有自己怪癖的成员的指针(例如p-&gt;*a(r.*a)(b, c))。 INVOKE 在 20.8.2 需求 [func.require] 中定义。

此外,使用std::function 的调用运算符的效果包括INVOKE(f, std::forward&lt;ArgTypes&gt;(args)..., R)(20.8.11.2.4 函数调用[func.wrap.func.inv]),这意味着为指针完成了“正确”的事情给会员。

实际上还有很多其他的东西也在标准中的 Callable/INVOKE 中定义,例如std::bindstd::thread、@ 987654335@和std::result_of*。

*: 特别是这意味着像

template<typename Functor>
typename std::result_of<Functor()>::type apply(Functor functor)
{ return std::forward<Functor>(functor)(); }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多