проблема с mem_fun_ref
-
09-09-2019 - |
Вопрос
У меня возникли проблемы с выяснением 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 строки.
Решение
Просто используй 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));
Другие советы
Эта проблема была объяснена в "Исключительном стиле C ++" Хербом Саттером, стр. 28-30.Вероятно, невозможно безопасно создать указатель на vector<int>::push_back
метод, поскольку необходимо быть уверенным в точной сигнатуре функции-члена, которая может быть неочевидной даже для vector<int>::push_back
в Стандартной библиотеке.Это происходит потому, что (в стандартной библиотеке):
- Сигнатура функции-члена с параметрами по умолчанию может быть заменена "двумя или более сигнатурами функции-члена с эквивалентным поведением.
- Сигнатура функции-члена может содержать дополнительные параметры по умолчанию.
В конце концов, Херб Саттер посоветовал, что
- Используйте mem_fun, Только не со стандартной библиотекой
- Используйте указатели на функции-члены, Только не со стандартной библиотекой
Я знаю, что ты сказал, что не хочешь использовать back_inserter
, вероятно, потому, что вы привели просто упрощенный пример кода.
Для тех, кому еще интересно, как сделать именно так то, что вы пытаетесь сделать, и с удовольствием используете это, используйте back_inserter
:
std::copy(a.begin(), a.end(), std::back_inserter(b));
Тем не менее, всегда есть other_mem_fun
, который я приготовил до того, как узнал о boost.Это могло бы подойти.