0

std::bind を使用すると、VS2010 では、オブジェクト自体ではなくポインターまたはイテレーターを渡すことで、データ メンバーをバインドできました。ただし、VS2012 では動作しないようです。

#include <vector>
#include <utility>
#include <iostream>
#include <functional>

using namespace std;

int main()
{
    vector<pair<string, int>> v; 
    v.push_back(make_pair("abc", 10));
    auto f = bind(&pair<string, int>::second, v.begin());
    int res = f();
    cout << res << endl;
    return 0;
}

( http://ideone.com/n1KWu )

GCC もこのコードを正常にコンパイルして実行しますが、VS2012 ではエラーが発生します。

error C2440: 'initializing' : cannot convert from 'std::_Do_call_ret<_Forced,_Ret,_Funx,_Btuple,_Ftuple>::type' to 'int'
1>          with
1>          [
1>              _Forced=false,
1>              _Ret=void,
1>              _Funx=std::_Pmd_wrap<int std::pair<std::string,int>::* ,int,std::pair<std::string,int>>,
1>              _Btuple=std::tuple<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<std::pair<std::string,int>>>>>,
1>              _Ftuple=std::tuple<>
1>          ]
1>          Expressions of type void cannot be converted to other types

イテレータまたはポインタの代わりに std::pair インスタンスを渡すと、VS2012 は満足することに注意してください。

ここで何が問題なのですか?

4

2 に答える 2

1

std::mem_fn(およびstd::bind) は、INVOKEファシリティに関して指定および実装されています。 を参照してください。§20.8.10 [func.memfn] p1

戻り値:fnfn(t, a2, ..., aN)が (20.8.2) と同等になる単純な呼び出しラッパー ( INVOKE(pm, t, a2, ..., aN)20.8.1)。

そのため、MSVC の の実装INVOKE、具体的には 4 番目の要件のバグである可能性が非常に高いです。

§20.8.2 [func.require] p1

次のように定義INVOKE(f, t1, t2, ..., tN)します。

  • (t1.*f)(t2, ..., tN)fクラスのメンバ関数へのポインタでありTt1Tのオブジェクト、型のオブジェクトへのT参照、または から派生した型のオブジェクトへの参照である場合T
  • ((*t1).*f)(t2, ..., tN)whenはクラスのfメンバー関数へのポインターであり、前の項目で説明した型のいずれでもない。Tt1
  • t1.*fN == 1およびがfクラスのメンバ データへのポインタでありTt1Tのオブジェクト、型のオブジェクトへのT参照、または から派生した型のオブジェクトへの参照である場合T
  • (*t1).*fN == 1f がクラスのメンバ データへのポインタであり、T t1の項目で説明した型のいずれでもない場合
  • f(t1, t2, ..., tN)他のすべての場合。

太字の部分は基本的に、 whenfが (あらゆる種類の) メンバー ポインターでt1あり、参照ではない場合、それを逆参照してからメンバー ポインターを適用しようとすることを示しています。イテレータは への参照ではないため、これはコードに当てはまるはずTです。GCC はこれを正しく実装します。

MS Connect でバグ レポートを提出することをお勧めします。

于 2012-10-24T00:27:27.517 に答える
0

このような参照を確認すると、最初の引数が

いくつかの引数にバインドされる関数オブジェクト

つまり、データ メンバーや変数はバインドできず、関数や関数に似たオブジェクトのみをバインドできるようにする必要があります。

C++11 標準 (セクション 20.8.9) から引用するには:

関数テンプレート bind は、引数として渡された呼び出し可能なオブジェクトを追加の引数にバインドするオブジェクトを返します。

于 2012-10-19T06:12:32.617 に答える