Как построить Boost BIMAP из статического списка?

У меня есть такой бимап:

using MyBimap = boost::bimaps::bimap<
boost::bimaps::unordered_set_of<A>,
boost::bimaps::unordered_set_of<B>>;

Я хочу построить его из статического списка инициализатора, как это можно сделать для std::map:

MyBimap map{{a1, b1}, {a2, b2}, {a3, b3}};

К сожалению, это не работает, потому что bimap не поддерживает списки инициализаторов, поэтому я попытался обойти это. В документации Boost перечислены следующие конструкторы:

 bimap();

template< class InputIterator >
bimap(InputIterator first,InputIterator last);

bimap(const bimap &);

Итак, я попробовал второй, как это:

std::vector<std::pair<A,B>> v{{a1, b1}, {a2, b2}, {a3, b3}};
MyBimap map(v.begin(), v.end());

Это также не сработало. В документации не совсем ясно, каких итераторов ожидает этот конструктор, но, очевидно, это не просто итератор std::pair<A, B> объекты. Тогда что этот конструктор ожидает для этого вида двуногих?

19

Решение

Итератор begin / end должен быть для последовательности значений bimap.

повышение :: bimap< A, B> :: value_type

Значение bimap очень похоже на std :: pair и может быть инициализировано с синтаксисом {a1, b1}. Кажется, что их вектор тоже работает, что обеспечивает пригодные для использования итераторы для конструктора.

Хорошо, вот пример, который компилируется и запускается для меня (gcc 4.8.2 —std = c ++ 11)

#include <vector>
#include <boost/bimap.hpp>

using namespace std;
int main() {
typedef boost::bimap< int, int > MyBimap;

std::vector<MyBimap::value_type > v{{1, 2}, {3, 4}, {5, 6}};

MyBimap M(v.begin(),v.end());

std::cout << "The size is " << M.size()
<< std::endl;

std::cout << "An entry is 1:" << M.left.at(1)
<< std::endl;
}
8

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

Я использую следующую «фабричную функцию», которая берет список инициализированных скобок и возвращает boost::bimap:

template <typename L, typename R>
boost::bimap<L, R>
makeBimap(std::initializer_list<typename boost::bimap<L, R>::value_type> list)
{
return boost::bimap<L, R>(list.begin(), list.end());
}

Использование:

auto myBimap = makeBimap<int, int>({{1, 2}, {3, 4}, {5, 6}});
22

C ++ новичок здесь: вы можете использовать boost :: assign для генерации инициализации. Я нашел это решение Вот.

Пример:

#include <boost/bimap.hpp>
#include <boost/assign.hpp>

//declare the type of bimap we want
typedef boost::bimap<int, std::string> bimapType;
//init our bimap
bimapType bimap = boost::assign::list_of< bimapType::relation >
( 1, "one"   )
( 2, "two"   )
( 3, "three" );

//test if everything works
int main(int argc, char **argv)
{
std::cout << bimap.left.find(1)->second << std::endl;
std::cout << bimap.left.find(2)->second << std::endl;
std::cout << bimap.left.find(3)->second << std::endl;
std::cout << bimap.right.find("one")->second << std::endl;
std::cout << bimap.right.find("two")->second << std::endl;
std::cout << bimap.right.find("three")->second << std::endl;

/* Output:
* one
* two
* three
* 1
* 2
* 3
*/
}
11

Это оставляет вектор для очистки, который может быть в некоторых случаях проблемой. Вот короткий вспомогательный класс, который также может решить вашу проблему. Поскольку экземпляр класса является временным, он немедленно очищается, где бы он ни использовался. Это основано на https://stackoverflow.com/a/1730798/3103767

// helper for bimap init (simple, lightweight version of boost::assign)
template <typename T, typename U>
class create_bimap
{
typedef boost::bimap< T, U > bimap_type;
typedef typename bimap_type::value_type value_type;
private:
boost::bimap<T, U> m_map;
public:
create_bimap(const T& left, const U& right)
{
m_map.insert( value_type(left, right) );
}

create_bimap<T, U>& operator()(const T& left, const U& right)
{
m_map.insert( value_type(left, right) );
return *this;
}

operator boost::bimap<T, U>()
{
return m_map;
}
};

Используйте следующим образом:

boost::bimap<string,int> myMap = create_bimap<string,int>
("c",1)
("b",2)
("a",3);
2
По вопросам рекламы [email protected]