2

このコードは VC2013 でのビルドに失敗します: (編集: ビルドに失敗する理由は尋ねていません)

#include <functional>

struct MyStruct
{
    std::function<void()> m_Func;
    MyStruct( const std::function<void()>& func) :  m_Func(func)   {}
};


int main()
{
    MyStruct rc( NULL );
    return 0;
}

エラーあり:

1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(283): error C2064: term does not evaluate to a function taking 0 arguments
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<int,false>::_ApplyX<_Rx,>(void)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Rx=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<int,false>::_ApplyX<_Rx,>(void)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Rx=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(226) : while compiling class template member function 'void std::_Func_impl<_MyWrapper,_Alloc,_Ret,>::_Do_call(void)'
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Ret=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Ret=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=int
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Fty=int
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=int
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Fty=int
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=int
1>  ,            _Fty=int
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=int
1>  ,            _Fty=int
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=int
1>  ,            _Fty=int
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=int
1>  ,            _Fty=int
1>          ]
1>          f:\work\teststdfunction\teststdfunction.cpp(16) : see reference to function template instantiation 'std::function<void (void)>::function<int>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=int
1>          ]
1>          f:\work\teststdfunction\teststdfunction.cpp(16) : see reference to function template instantiation 'std::function<void (void)>::function<int>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=int
1>          ]

(最後に報告された 2 つのエラーの '_Fx=int' に注意してください)。

MyStruct rc(NULL)に変更するMyStruct rc(nullptr)とエラーが解決するので、私はそれで暮らすことができます。ただし、2 つのことが謎のままです。

1) MyStruct ctor から const 修飾子を削除するMyStruct( std::function<void()>& func)と、非常に異なるエラーが発生します。

1>f:\work\main\dev\common\teststdfunction\teststdfunction\teststdfunction.cpp(16): エラー C2664: 'MyStruct::MyStruct(const MyStruct &)': 引数 1 を 'int' から 'std' に変換できません::関数 &'

これは元のエラーよりも理にかなっており、NULL を nullptr に修正しても解決しません。int (または nullptr) が へのキャストを拒否するstd::function<>&のに、 a へのキャストに同意するのはconst std::function<>&なぜですか?

2) 元のコードは VS2010 で期待どおりにコンパイルされ、動作します。あいまいな VS2010 ライブラリのバグですか?


編集: const/non const の質問に関する限り、関連するキャストと潜在的な型の不一致はおそらく赤いニシンだと思います。渡された引数 (NULL または nullptr) はリテラルであり、したがって const です。非 const 参照にバインドすることはできません。例えば:

const int& a = 8;   // Ok
int& b = 9;    // error C2440: 'initializing' : cannot convert from 'int' to 'int &' 

そうですか?私はまだ何かを見逃していますか?

4

2 に答える 2

2

ここでの特別な点は、コンストラクター テンプレートの制約とその他の暗黙的な変換に関係しています。

nullptr機能する理由std::functionは、特定のコンストラクターがそれを取るためです。関数テンプレートは優先順位が低く、他のすべてが等しいため、このコンストラクターは常にその引数に最適です。

通常、0暗黙的に変換されnullptr、それで問題ありません。問題は、関数オブジェクトから構築する制約のない関数テンプレート コンストラクターにも渡すことができることです。これは暗黙的な変換を必要としないため、すべてが等しくないため、このコンストラクターが優先されます。その結果int、有効な関数オブジェクトではないというエラーが発生します。

libstdc++ と libc++ は、コンストラクターを制約するこの問題に対する C++14 修正を実装しているため、この動作を示しません。C++11 ではそうではなかったため、この動作は C++11 実装に完全に準拠しています。

この種の問題は、NULL使用してはいけないひどいものです。実際、VS2010 チームは、C++ の他のすべての機能、特に C++11 との相互作用が非常に悪いnullptrため、土壇場で追加機能としてドアを急がなければなりませんでした。NULL

const対非参照についてconstは、他の回答でその問題が適切に説明されています。

C++ 14 で出荷された制約付きコンストラクターの修正なしで使用する場合に見つけることができる他の WTF がありますstd::function。これは唯一のものではありません。要するに、これは C++11 標準の欠陥であり、VSの欠陥ではないということです。VS2010 のコンパイルは、おそらくコンパイラのオーバーロード解決のバグです。

于 2014-12-07T14:59:22.650 に答える
0

Taから a へのキャストはU&機能しません。これは意図的なものです。にキャストできますU const&。その理由は、一時的な U オブジェクトへの変更が T 値に反映されないためです。

VS2010 はこの点で少しバグがあり、キャストを許可しました (ただし、適切な設定では、それについて警告します)。

于 2014-12-07T14:28:41.430 に答える