Mem_fun_ref неприятности - PullRequest
       27

Mem_fun_ref неприятности

4 голосов
/ 04 июня 2009

У меня проблемы с выяснением mem_fun_ref. Я должен признать, я обычно использую функторы для такого рода вещей, так как они могут быть ориентированы на скорость и прибыль. Однако этот код не будет узким местом, и я хотел попробовать это.

Вот пример того, что я хочу сделать. Я знаю, что есть и другие способы сделать это. Я не хочу использовать copy, я не хочу использовать функции-члены диапазона, я не хочу использовать back_inserter. Я специально хочу использовать mem_fun_ref. Это простой пример, реальный случай гораздо сложнее. Тем не менее, я действительно не знаю, почему это не так, но я не знаком с mem_fun_ref или mem_fun.

Вот что я хочу работать:

#include <list>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

int main()
{
    list<int> a;
    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
    vector<int> b;

    // should work like magic!
    for_each(a.begin(), a.end(), bind1st(mem_fun_ref(&vector<int>::push_back), b));
}

Но я получаю 3 ошибки:

1>c:\program files\microsoft visual studio 9.0\vc\include\functional(276) : error C2529: '_Right' : reference to reference is illegal
1>c:\program files\microsoft visual studio 9.0\vc\include\functional(281) : error C2529: '_Right' : reference to reference is illegal
1>c:\program files\microsoft visual studio 9.0\vc\include\functional(282) : error C2535: 'void std::binder1st<_Fn2>::operator ()(const int &(&)) const' : member function already defined or declared
1>        with
1>        [
1>            _Fn2=std::mem_fun1_ref_t<void,std::vector<int>,const int &>
1>        ]
1>        c:\program files\microsoft visual studio 9.0\vc\include\functional(276) : see declaration of 'std::binder1st<_Fn2>::operator ()'
1>        with
1>        [
1>            _Fn2=std::mem_fun1_ref_t<void,std::vector<int>,const int &>
1>        ]

reference to reference is illegal заставляет меня думать, что функция должна принимать параметр по значению. Но, конечно, это невозможно изменить в vector, и это невозможно изменить в моем коде. Есть ли простое изменение, чтобы заставить это работать? Мне нужно решение это 1-лайнер.

Ответы [ 4 ]

4 голосов
/ 04 июня 2009

Просто используйте bind. mem_fun версии слишком сложны.

for_each(a.begin(), a.end(),
  boost::bind(&vector<int>::push_back, boost::ref(b), _1));

Другой способ, который не требует использования ref, - передать указатель на вектор, который нужно изменить:

for_each(a.begin(), a.end(),
  boost::bind(&vector<int>::push_back, &b, _1));
2 голосов
/ 30 июня 2009

Эта проблема была объяснена в «Исключительном стиле C ++» Хербом Саттером, стр. 28-30. Вероятно, невозможно безопасно создать указатель на метод vector<int>::push_back, так как необходимо быть уверенным в точной подписи функции-члена, что может быть неочевидно даже для vector<int>::push_back в стандартной библиотеке. Это потому, что (в стандартной библиотеке):

  1. Подпись функции-члена с параметрами по умолчанию может быть заменена "двумя или более сигнатурами функции-члена с эквивалентным поведением.
  2. Подпись функции-члена может иметь дополнительные параметры по умолчанию.

В конце концов, Херб Саттер посоветовал

  1. Использовать mem_fun, только не со стандартной библиотекой
  2. Использование указателей на функции-члены, но не в стандартной библиотеке
0 голосов
/ 04 июня 2009

Тем не менее, всегда есть other_mem_fun, которые я приготовил до того, как узнал о повышении. Это может подойти.

0 голосов
/ 04 июня 2009

Я знаю, что вы сказали, что не хотите использовать back_inserter, возможно, потому что вы дали только упрощенный пример кода.

Для всех, кто интересуется, как сделать точно , что вы пытаетесь сделать, и с удовольствием его используете, используйте back_inserter:

std::copy(a.begin(), a.end(), std::back_inserter(b));
...