Связывающие данные элементы не работают в VS2012?

При использовании 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 будет счастлив.

В чем здесь проблема?

0

Решение

std::mem_fn (а также std::bind) определен и реализован в терминах INVOKE средство, см. §20.8.10 [func.memfn] p1

Возвращает: Простая обертка вызовов (20.8.1) fn такое что выражение fn(t, a2, ..., aN) эквивалентно INVOKE(pm, t, a2, ..., aN) (20.8.2).

Таким образом, это очень вероятно, ошибка в реализации MSVC INVOKEконкретно четвертое требование:

§20.8.2 [func.require] p1

определять INVOKE(f, t1, t2, ..., tN) следующее:

  • (t1.*f)(t2, ..., tN) когда f указатель на функцию-член класса T а также t1 является объектом типа T или ссылка на объект типа T или ссылка на объект типа, производного от T;
  • ((*t1).*f)(t2, ..., tN) когда f указатель на функцию-член класса T а также t1 не является одним из типов, описанных в предыдущем пункте;
  • t1.*f когда N == 1 а также f указатель на данные члена класса T а также t1 является объектом типа T или ссылка на объект типа T или ссылка на объект типа, производного от T;
  • (*t1).*f когда N == 1 и f — указатель на данные члена класса T а также t1 не является одним из типов, описанных в предыдущем пункте;
  • f(t1, t2, ..., tN) во всех остальных случаях.

Жирная часть в основном говорит, что когда f указатель члена (любого типа) и t1 не является ссылкой, попробуйте разыменовать его и после этого применить указатель на член. Это должно иметь место для вашего кода, так как итератор не является ссылкой на T, GCC реализует это правильно.

Советую подать отчет об ошибке в MS Connect.

1

Другие решения

Если вы проверите ссылку как это вы увидите, что первые аргументы должны быть

функциональный объект, который будет связан с некоторыми аргументами

Другими словами, вы не должны иметь возможность связывать элементы данных или переменные, только функции и функционально-подобные объекты.

Чтобы процитировать из стандарта C ++ 11 (раздел 20.8.9):

Функция template bind возвращает объект, который связывает вызываемый объект, переданный в качестве аргумента, с дополнительными аргументами.

0

По вопросам рекламы ammmcru@yandex.ru