RSC  0.16.0
AssociativeProxy.h
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project
4  *
5  * Copyright (C) 2010, 2011 Jan Moringen
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #pragma once
28 
29 #include <boost/type_traits/remove_reference.hpp>
30 #include <boost/noncopyable.hpp>
31 
32 #include "../runtime/TypeStringTools.h"
33 #include "NoSuchKey.h"
34 #include "ContainerProxy.h"
35 #include "Accessors.h"
36 #include "detail/ForceConst.h"
37 #include "detail/PairWorkaround.h"
38 
39 namespace rsc {
40 namespace patterns {
41 
42 namespace detail {
43 
44 template<typename Key, typename Mapped, typename Accessor>
45 struct pair_adapter {
47 
48  result_type operator()(const std::pair<Key, Mapped>& pair) const throw () {
49  return make_pair<Key, typename Accessor::result_type> (pair.first,
51  }
52 
53  Accessor accessor;
54 };
55 
56 }
57 
61 template<typename Container, typename Accessor = pass_through>
62 class AssociativeProxy: public ContainerProxy<Container,
63  detail::pair_adapter<typename Container::key_type,
64  typename Container::mapped_type, Accessor> > {
65 public:
66  typedef typename Container::key_type key_type;
67  typedef typename boost::remove_reference<typename Accessor::result_type>::type
69 
70  typedef detail::pair_adapter<typename Container::key_type,
71  typename Container::mapped_type, Accessor> base_accessor_type;
73 
74  AssociativeProxy(Container& container);
75 
80  operator[](const key_type& key) const;
81 
85  typename Accessor::result_type
86  operator[](const key_type& key);
87 
89  find(const key_type& key) const throw () {
90  return typename base_type::const_iterator(base_type::container.find(key),
91  base_type::accessor);
92  }
93 
94  typename base_type::iterator
95  find(const key_type& key) throw () {
96  return typename base_type::iterator(base_type::container.find(key),
97  base_type::accessor);
98  }
99 
100 private:
101  typedef Accessor accessor_type;
102 
103  accessor_type accessor;
104 };
105 
106 template<typename Container>
107 class AssociativeProxy<Container, pass_through> : public ContainerProxy<
108  Container, pass_through> {
109 public:
110  typedef typename Container::key_type key_type;
111  typedef typename Container::mapped_type mapped_type;
112 
115 
116  AssociativeProxy(Container& container);
117 
122  operator[](const key_type& key) const;
123 
127  mapped_type&
128  operator[](const key_type& key);
129 
131  find(const key_type& key) const throw ();
132 
134  find(const key_type& key) throw ();
135 private:
137 };
138 
139 // AssociativeProxy implementation
140 
141 template<typename Container, typename Accessor>
143  base_type(container) {
144 }
145 
146 template<typename Container, typename Accessor>
148  Container, Accessor>::operator[](const key_type& key) const {
149  typename Container::const_iterator it;
150  if ((it = base_type::container.find(key)) == base_type::container.end()) {
151  throw no_such_key(type_string("no such key in container: `%1%'",
152  "no such key in container", key));
153  }
154 
155  return this->accessor(it->second);
156 }
157 
158 template<typename Container, typename Accessor>
160  const key_type& key) {
161  typename Container::iterator it;
162  if ((it = base_type::container.find(key)) == base_type::container.end()) {
163  throw no_such_key(type_string("no such key in container: `%1%'",
164  "no such key in container", key));
165  }
166 
167  return this->accessor(it->second);
168 }
169 
170 // AssociativeProxy<Container, pass_through> implementation
171 
172 template<typename Container>
174  Container& container) :
175  base(container) {
176 }
177 
178 template<typename Container>
179 typename detail::force_const<
182  typename Container::const_iterator it;
183  if ((it = base_type::container.find(key)) == base_type::container.end()) {
184  throw no_such_key(type_string("no such key in container: `%1%'",
185  "no such key in container", key));
186  }
187 
188  return it->second;
189 }
190 
191 template<typename Container>
194  typename Container::iterator it;
195  if ((it = base_type::container.find(key)) == base_type::container.end()) {
196  throw no_such_key(type_string("no such key in container: `%1%'",
197  "no such key in container", key));
198  }
199 
200  return it->second;
201 }
202 
203 template<typename Container>
205  Container, pass_through>::find(const key_type& key) const throw () {
206  return base_type::container.find(key);
207 }
208 
209 template<typename Container>
211  Container, pass_through>::find(const key_type& key) throw () {
212  return base::container.find(key);
213 }
214 
215 }
216 }
detail::pair< Key, typename Accessor::result_type > result_type
ContainerProxy< Container, pass_through > base_type
base_type::const_iterator find(const key_type &key) const
boost::transform_iterator< Accessor, typename Container::iterator, typename Accessor::result_type > iterator
detail::force_const< typename Accessor::result_type >::type operator[](const key_type &key) const
boost::mpl::if_< typename boost::is_reference< T >::type, typename boost::add_reference< typename boost::add_const< typename boost::remove_reference< T >::type >::type >::type, typename boost::add_const< T >::type >::type type
Definition: ForceConst.h:43
_T2 second
second is a copy of the second object
detail::pair_adapter< typename Container::key_type, typename Container::mapped_type, Accessor > base_accessor_type
_T1 first
first is a copy of the first object
boost::remove_reference< typename Accessor::result_type >::type mapped_type
ContainerProxy< Container, pass_through > base
boost::transform_iterator< Accessor, typename Container::const_iterator, typename detail::force_const< typename Accessor::result_type >::type > const_iterator
result_type operator()(const std::pair< Key, Mapped > &pair) const
ContainerProxy< Container, base_accessor_type > base_type
pair holds two objects of arbitrary type.
AssociativeProxy(Container &container)
base_type::iterator find(const key_type &key)