Очевидный способ конвертировать bimap в std :: map, похоже, не работает. Ниже правильный / хороший способ конвертации? Есть ли лучший / короткий путь?
typedef boost::bimap<int, std::string> MapType;
MapType _bimap;
//Fill _bimap
MapType::left_map& lmap = _bimap.left;
//std::map<int, std::string> bmap(lmap.begin(), lmap.end()); //THIS DOESNT WORK
std::map<int, std::string> bmap;
BOOST_FOREACH(MapType::left_const_reference entry, lmap)
{
bmap[entry.first] = entry.second;
}
Значения из bimap
не может быть непосредственно назначен на map
потому что существует проблема типа (игнорируя более очевидную проблему постоянства значения):
Когда итератор левого представления bimap разыменовывается, возвращаемый тип совместим с сигнатурой с помощью std :: pair< const A, const B>
(источник)
А также :
Тип совместим с сигнатурой с другим типом, если он имеет ту же сигнатуру для функций и метаданных. Предварительные условия, постусловия и порядок операций не обязательно должны быть одинаковыми.
Это означает, что нет никакой гарантии, что ваш bimap value_type может быть назначен или скопирован в карту value_type. На самом деле это не так:
typedef boost::bimap<int, std::string> BiMapType;
typedef std::map<int, std::string> MapType;
BiMapType bimap;
BiMapType::left_value_type t1 = *(bimap.left.begin()); // Mandatory for compilation on my version at least
MapType::value_type t2(t1);
Это ужасно потерпит неудачу (то же самое, если вы попытаетесь t2 = t1;
)
Так что либо вы найдете способ конвертировать значения-значения, либо сохраните их с помощью for_each / transform / copy … идиома.
В комментарии @CharlesPehlivanian (который он, возможно, также предоставит в качестве ответа) здесь есть замечательное решение, которое нужно использовать. boost::trasnform_iterator
,
Для этого вы должны предоставить transformer
функтор (он не работает с необработанной лямбда, вы должны использовать структуру с operator()
а также result_type
или std::function
), который преобразует входное значение итератора в выходное значение:
typedef std::function<MapType::value_type (const BiMapType::left_value_type&)>
Transformer;
Transformer transformer_func = [](const BiMapType::left_value_type& elem)
{
return std::make_pair(elem.first, elem.second);
};
Тогда вам просто нужно обернуть начало и конец итератора boost::make_transform_iterator
:
auto begin = boost::make_transform_iterator(bimap.left.begin(), transformer_func);
auto end = boost::make_transform_iterator(bimap.left.end(), transformer_func);
Вот весь код:
#include <boost/bimap.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <map>
int main(int argc, char const *argv[])
{
typedef boost::bimap<int, std::string> BiMapType;
typedef std::map<int, std::string> MapType;
typedef std::function<MapType::value_type (const BiMapType::left_value_type&)>
Transformer;
BiMapType bimap;Transformer transformer_func = [](const BiMapType::left_value_type& elem)
{
return std::make_pair(elem.first, elem.second);
};
auto begin = boost::make_transform_iterator(bimap.left.begin(), transformer_func);
auto end = boost::make_transform_iterator(bimap.left.end(), transformer_func);
MapType map(begin, end);
return 0;
}
Других решений пока нет …