• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Boost.MultiIndex example of a bidirectional map.
2  *
3  * Copyright 2003-2009 Joaquin M Lopez Munoz.
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * See http://www.boost.org/libs/multi_index for library home page.
9  */
10 
11 #if !defined(NDEBUG)
12 #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
13 #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
14 #endif
15 
16 #include <boost/multi_index_container.hpp>
17 #include <boost/multi_index/member.hpp>
18 #include <boost/multi_index/ordered_index.hpp>
19 #include <iostream>
20 #include <string>
21 
22 using boost::multi_index_container;
23 using namespace boost::multi_index;
24 
25 /* tags for accessing both sides of a bidirectional map */
26 
27 struct from{};
28 struct to{};
29 
30 /* The class template bidirectional_map wraps the specification
31  * of a bidirectional map based on multi_index_container.
32  */
33 
34 template<typename FromType,typename ToType>
35 struct bidirectional_map
36 {
37   struct value_type
38   {
value_typebidirectional_map::value_type39     value_type(const FromType& first_,const ToType& second_):
40       first(first_),second(second_)
41     {}
42 
43     FromType first;
44     ToType   second;
45   };
46 
47 #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
48     defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\
49     defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\
50            (BOOST_INTEL_CXX_VERSION<=700)
51 
52 /* see Compiler specifics: Use of member_offset for info on member<> and
53  * member_offset<>
54  */
55 
56   BOOST_STATIC_CONSTANT(unsigned,from_offset=offsetof(value_type,first));
57   BOOST_STATIC_CONSTANT(unsigned,to_offset  =offsetof(value_type,second));
58 
59   typedef multi_index_container<
60     value_type,
61     indexed_by<
62       ordered_unique<
63         tag<from>,member_offset<value_type,FromType,from_offset> >,
64       ordered_unique<
65         tag<to>,  member_offset<value_type,ToType,to_offset> >
66     >
67   > type;
68 
69 #else
70 
71   /* A bidirectional map can be simulated as a multi_index_container
72    * of pairs of (FromType,ToType) with two unique indices, one
73    * for each member of the pair.
74    */
75 
76   typedef multi_index_container<
77     value_type,
78     indexed_by<
79       ordered_unique<
80         tag<from>,member<value_type,FromType,&value_type::first> >,
81       ordered_unique<
82         tag<to>,  member<value_type,ToType,&value_type::second> >
83     >
84   > type;
85 
86 #endif
87 };
88 
89 /* a dictionary is a bidirectional map from strings to strings */
90 
91 typedef bidirectional_map<std::string,std::string>::type dictionary;
92 
main()93 int main()
94 {
95   dictionary d;
96 
97   /* Fill up our microdictionary. first members Spanish, second members
98    * English.
99    */
100 
101   d.insert(dictionary::value_type("hola","hello"));
102   d.insert(dictionary::value_type("adios","goodbye"));
103   d.insert(dictionary::value_type("rosa","rose"));
104   d.insert(dictionary::value_type("mesa","table"));
105 
106 
107   std::cout<<"enter a word"<<std::endl;
108   std::string word;
109   std::getline(std::cin,word);
110 
111 #if defined(BOOST_NO_MEMBER_TEMPLATES) /* use global get<> and family instead */
112 
113   dictionary::iterator it=get<from>(d).find(word);
114   if(it!=d.end()){
115     std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
116   }
117   else{
118     nth_index<dictionary,1>::type::iterator it2=get<1>(d).find(word);
119     if(it2!=get<1>(d).end()){
120       std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
121     }
122     else std::cout<<"No such word in the dictionary"<<std::endl;
123   }
124 
125 #else
126 
127   /* search the queried word on the from index (Spanish) */
128 
129   dictionary::iterator it=d.get<from>().find(word);
130   if(it!=d.end()){ /* found */
131 
132     /* the second part of the element is the equivalent in English */
133 
134     std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
135   }
136   else{
137     /* word not found in Spanish, try our luck in English */
138 
139     dictionary::index<to>::type::iterator it2=d.get<to>().find(word);
140     if(it2!=d.get<to>().end()){
141       std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
142     }
143     else std::cout<<"No such word in the dictionary"<<std::endl;
144   }
145 
146 #endif
147 
148   return 0;
149 }
150