Я пытаюсь использовать связывание для создания функции, которая:
Для этого я пытаюсь использовать boost :: bind:
typedef map<int,int>::const_iterator (map<int,int>::*const_begin_end) () const;
bind(&pair<const int,int>::first, bind(static_cast<const_begin_end>(&map<int, int>::begin), _1));
Это не работает, потому что результат начала должен быть разыменован. Я думал что-то вроде
bind(&pair<const int,int>::first, bind(&operator*, bind(static_cast<const_begin_end>(&map<int, int>::begin), _1)));
Но это не сработает, так как нет глобального оператора *.
Вопросы:
я очень рекомендую Boost.Phoenix, это моя библиотека, когда речь заходит о написании функторов на лету в C ++ 03. Это превосходная альтернатива Boost.Bind — эта библиотека показывает свой возраст.
Например, Phoenix позволил нам использовать операторы на своих функторах для представления фактического использования этого оператора при вызове функтора. таким образом arg1 + arg2
является функтором, который возвращает сумму своих первых двух операндов. Это сильно сокращает bind
шум. Первая попытка может выглядеть так:
bind(&pair<const int, int>::first
, *bind(static_cast<const_begin_end>(&map<int, int>::begin), arg1)) )
(LWS демо)
Но другой сильной стороной Phoenix является то, что он поставляется с некоторыми батареями. В нашем случае мы очень заинтересованы в <boost/phoenix/stl/container.hpp>
потому что это включает в себя некоторую ленивую версию знакомых операций контейнеров, в том числе begin
, Это очень удобно в нашем случае:
// We don't need to disambiguate which begin member we want anymore!
bind(&pair<const int, int>::first, *begin(arg1))
(LWS демо)
В заключение добавлю, что выражения связывания в C ++ 11 определены так, что указатели на элементы работают над что-нибудь который использует operator*
, Так что из коробки вы можете сделать:
bind(&pair<const int, int>::first, bind(static_cast<begin_type>(&std::map<int, int>::begin), _1))
(LWS демо)
Вы можете вызывать связывание с указателями на функции-члены, а операторы-члены — это не что иное, как функции-члены:
const_begin_end pBegin = &map<int,int>::begin;
x = bind(&std::pair::first,
bind(&std::map<int, int>::const_iterator::operator*,
bind(pBegin, _1)
);
А если серьезно, вы также можете просто написать правильную функцию, которая делает то, что вам нужно, вместо этого нечитаемого беспорядка boost.bind (вы можете сказать «ремонтопригодность»?).
Итак, для C ++ 03 функция:
template <class Map>
typename Map::key_type keyBegin(Map const& m)
{
return m.begin().first;
}
или функтор C ++ 03 (вы можете определить его локально внутри своей функции)
struct KeyBegin
{
typedef std::map<int, int> IntMap;
int operator()(IntMap const& m) {
return m.begin().first;
}
};
или лямбда на C ++ 11 (более читабельная, чем оргия связывания):
auto keyBegin = [](std::map<int, int> const& m) -> int {
return std::begin(m).first;
};