Задать вопрос

Std::bind. Bind to member data?

Захотелось испытать красивый и мощный std::bind (точнее std::tr1::bind, пока еще нужно работать со старым стандартом, платформа Windows, msvc10), который по сравнению std::bind1st и std::bind2nd, кроме всего прочего, решает проблему ссылки на ссылку… да и отвыкать от старых биндеров нужно.

Мне понравилось то, что с помощью std::bind можно достучаться до какого-нибуть члена данных, т.е., например:
struct Data
{
	int d1;
	double d2;
	// ...
};

using namespace std::placeholders;
// по сути, мы создали функцию, которая принимает экземпляр Data и возвращает значение Data::d2
std::bind(&Data::d2, _1);

// т.е.
Data myData = { 1, 10.0 };
// value == 10.0
double value = std::bind(&Data::d2, _1)(myData);



Таким образом, допустим, нам нужно найти элемент контейнера (который содержит экземпляры Data), значение d2 которого равно некоторой величине. Итак, c помощью std::bind2nd:
struct MyPredicate
	: std::binary_function<Data, double, bool>
{
	bool operator()(Data d, double value) const
	{
		return (d.d2 == value);
	}
};

// ...
enum { SIZE = 10 };
Data arr[SIZE] = {};

const Data* const begin = arr;
const Data* const end = arr + SIZE;

double value = 0.0;
const Data* const pos = std::find_if(begin, end, std::bind2nd(MyPredicate(), value));
// ...



Но с помощью вышеупомянутой возможности std::bind-а, всё это можно сделать проще, казалось-бы:
const Data* const pos = std::find_if(begin, end,
	std::bind(std::equal_to<double>(), std::bind(&Data::d2, _1), value));


но, судя по ворнингам компилятора, где-то std::bind возвращает адрес локальной переменной и вместо &Data::d2 передаётся невалидный указатель.


Так вот, хотелось бы узнать, может быть, корректную реализацию подобного или я совсем чужь несу и это всё никому не нужно.
  • Вопрос задан
  • 5062 просмотра
Подписаться 3 Оценить 3 комментария
Пригласить эксперта
Ответы на вопрос 2
ixSci
@ixSci
По поводу bind и msvc: он весьма плохо написан и содержит большое количество багов, поэтому можете не удивляться его странному поведению в студиях(включая 2012)
я совсем чужь несу и это всё никому не нужно.

Именно так, std::bind устарел еще не успев стать полноценной частью стандарта. Используйте лямбды.
Ответ написан
Mephi1984
@Mephi1984
Вы можете получать объекты по ссылке. Для этого можете воспользоваться std::ref и std::cref
en.cppreference.com/w/cpp/utility/functional/ref

Напишите, если поможет или не поможет. У меня компилятор далеко, но как приду домой, могу проверить подробнее.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы