Захотелось испытать красивый и мощный
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
передаётся невалидный указатель.
Так вот, хотелось бы узнать, может быть, корректную реализацию подобного или я совсем чужь несу и это всё никому не нужно.