Конвертировать boost :: bimap в std :: map

Очевидный способ конвертировать 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;
}

4

Решение

Значения из 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;
}

http://coliru.stacked-crooked.com/a/8fae0d47ca4b72a1

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]