7

次のコードは 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>          ]
4

2 に答える 2

5

次の構文は機能し、少なくとも短くなります。

std::function<int (Zot*)> fn = std::mem_fn(&Zot::A);
于 2012-08-27T15:57:50.920 に答える
2

はい、うまくいくはずです。の適切なコンストラクター (例: template<class F> function(F f);) のファンクター引数に関する要件の 1 つは、次のstd::function<R(ArgsTypes...)>とおりです。

f は、引数の型と戻り値の型に対してCallable (20.8.11.2) でなければなりません。ArgTypesR

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

次に、「引数の型と戻り値の型の呼び出し可能」は、疑似式の観点から定義された標準の準概念 (概念の欠如のため)です。この疑似式は、通常の呼び出し構文 (例: ) で呼び出される通常のファンクタを、独自の癖を持つメンバーへのポインタ (例:または) と統合します。INVOKEは、20.8.2 要件 [func.require] で定義されています。ArgTypesRINVOKE(f, declval<ArgTypes>()..., R)f(a, b, c)p->*a(r.*a)(b, c)

さらに、std::functionincludeの呼び出し演算子を使用する効果INVOKE(f, std::forward<ArgTypes>(args)..., R)(20.8.11.2.4 関数呼び出し [func.wrap.func.inv]) は、メンバーへのポインターに対して「正しい」ことが行われることを意味します。

実際には、標準でCallable / INVOKEstd::bindに関しても定義されているものが他にもたくさんあります。たとえば、std::threadstd::reference_wrapperstd::result_of* などです。

*: 特に、これは次のようなことを意味します

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

少なくともその理由で問題があります。

于 2012-08-27T16:38:43.343 に答える