c++ - ¿Cómo construir Boost bimap desde la lista estática?
c++11 boost-bimap (4)
Tengo un bimap como este:
using MyBimap = boost::bimaps::bimap<
boost::bimaps::unordered_set_of<A>,
boost::bimaps::unordered_set_of<B>>;
Quiero construirlo a partir de una lista de inicialización estática, como se puede hacer para std::map
:
MyBimap map{{a1, b1}, {a2, b2}, {a3, b3}};
Desafortunadamente, no funciona porque bimap
no admite las listas de inicialización, así que intenté una solución. La documentación de Boost enumera los siguientes constructores:
bimap();
template< class InputIterator >
bimap(InputIterator first,InputIterator last);
bimap(const bimap &);
Así que probé el segundo, así:
std::vector<std::pair<A,B>> v{{a1, b1}, {a2, b2}, {a3, b3}};
MyBimap map(v.begin(), v.end());
Tampoco funcionó. La documentación no es exactamente clara qué tipo de iteradores espera este constructor, pero aparentemente no es simplemente un iterador de objetos std::pair<A, B>
. Entonces, ¿qué espera este constructor para este tipo de bimap?
El inicio / final del iterador debe ser para una secuencia de valores bimap.
boost :: bimap <A, B> :: value_type
Un valor bimap es muy parecido a un par std :: y se puede inicializar con la sintaxis {a1, b1}. Un vector de ellos parece funcionar también, lo que proporciona iteradores útiles para el constructor.
Ok, aquí hay un ejemplo que compila y ejecuta para mí (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;
}
Esto deja un vector para limpiar, lo que en algunos casos podría ser un problema. Aquí hay una breve clase de ayuda que también podría resolver su problema. Como la instancia de clase es temporal, se limpia inmediatamente donde sea que se use. Esto se basa en https://.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;
}
};
Use de la siguiente manera:
boost::bimap<string,int> myMap = create_bimap<string,int>
("c",1)
("b",2)
("a",3);
Principiante de C ++ aquí: Puedes usar boost :: assign para generar la inicialización. Encontré esta solución here .
Ejemplo:
#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
*/
}
Utilizo la siguiente "función de fábrica" que toma una lista de inicializadores y devuelve un 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());
}
Uso:
auto myBimap = makeBimap<int, int>({{1, 2}, {3, 4}, {5, 6}});