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