/* Boost.MultiIndex example of a bidirectional map. * * Copyright 2003-2009 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See http://www.boost.org/libs/multi_index for library home page. */ #if !defined(NDEBUG) #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE #endif #include <boost/multi_index_container.hpp> #include <boost/multi_index/member.hpp> #include <boost/multi_index/ordered_index.hpp> #include <iostream> #include <string> using boost::multi_index_container; using namespace boost::multi_index; /* tags for accessing both sides of a bidirectional map */ struct from{}; struct to{}; /* The class template bidirectional_map wraps the specification * of a bidirectional map based on multi_index_container. */ template<typename FromType,typename ToType> struct bidirectional_map { struct value_type { value_type(const FromType& first_,const ToType& second_): first(first_),second(second_) {} FromType first; ToType second; }; #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\ defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\ defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\ (BOOST_INTEL_CXX_VERSION<=700) /* see Compiler specifics: Use of member_offset for info on member<> and * member_offset<> */ BOOST_STATIC_CONSTANT(unsigned,from_offset=offsetof(value_type,first)); BOOST_STATIC_CONSTANT(unsigned,to_offset =offsetof(value_type,second)); typedef multi_index_container< value_type, indexed_by< ordered_unique< tag<from>,member_offset<value_type,FromType,from_offset> >, ordered_unique< tag<to>, member_offset<value_type,ToType,to_offset> > > > type; #else /* A bidirectional map can be simulated as a multi_index_container * of pairs of (FromType,ToType) with two unique indices, one * for each member of the pair. */ typedef multi_index_container< value_type, indexed_by< ordered_unique< tag<from>,member<value_type,FromType,&value_type::first> >, ordered_unique< tag<to>, member<value_type,ToType,&value_type::second> > > > type; #endif }; /* a dictionary is a bidirectional map from strings to strings */ typedef bidirectional_map<std::string,std::string>::type dictionary; int main() { dictionary d; /* Fill up our microdictionary. first members Spanish, second members * English. */ d.insert(dictionary::value_type("hola","hello")); d.insert(dictionary::value_type("adios","goodbye")); d.insert(dictionary::value_type("rosa","rose")); d.insert(dictionary::value_type("mesa","table")); std::cout<<"enter a word"<<std::endl; std::string word; std::getline(std::cin,word); #if defined(BOOST_NO_MEMBER_TEMPLATES) /* use global get<> and family instead */ dictionary::iterator it=get<from>(d).find(word); if(it!=d.end()){ std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl; } else{ nth_index<dictionary,1>::type::iterator it2=get<1>(d).find(word); if(it2!=get<1>(d).end()){ std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl; } else std::cout<<"No such word in the dictionary"<<std::endl; } #else /* search the queried word on the from index (Spanish) */ dictionary::iterator it=d.get<from>().find(word); if(it!=d.end()){ /* found */ /* the second part of the element is the equivalent in English */ std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl; } else{ /* word not found in Spanish, try our luck in English */ dictionary::index<to>::type::iterator it2=d.get<to>().find(word); if(it2!=d.get<to>().end()){ std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl; } else std::cout<<"No such word in the dictionary"<<std::endl; } #endif return 0; }