1 /*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 http://spirit.sourceforge.net/
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM)
10 #define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM
12 #include <boost/fusion/support/category_of.hpp>
13 #include <boost/spirit/home/x3/support/unused.hpp>
14 #include <boost/fusion/include/deque.hpp>
15 #include <boost/mpl/identity.hpp>
16 #include <boost/type_traits/make_void.hpp>
23 namespace boost { namespace spirit { namespace x3 { namespace traits
25 ///////////////////////////////////////////////////////////////////////////
26 // This file contains some container utils for stl containers.
27 ///////////////////////////////////////////////////////////////////////////
31 template <typename T, typename Enabler = void>
32 struct is_container_impl : mpl::false_ {};
35 struct is_container_impl<T, void_t<
36 typename T::value_type, typename T::iterator,
37 typename T::size_type, typename T::reference> > : mpl::true_ {};
39 template <typename T, typename Enabler = void>
40 struct is_associative_impl : mpl::false_ {};
43 struct is_associative_impl<T, void_t<typename T::key_type>>
48 using is_container = typename detail::is_container_impl<T>::type;
51 using is_associative = typename detail::is_associative_impl<T>::type;
53 ///////////////////////////////////////////////////////////////////////////
57 struct remove_value_const : mpl::identity<T> {};
60 struct remove_value_const<T const> : remove_value_const<T> {};
62 template <typename F, typename S>
63 struct remove_value_const<std::pair<F, S>>
65 typedef typename remove_value_const<F>::type first_type;
66 typedef typename remove_value_const<S>::type second_type;
67 typedef std::pair<first_type, second_type> type;
71 ///////////////////////////////////////////////////////////////////////
72 template <typename Container, typename Enable = void>
73 struct container_value
74 : detail::remove_value_const<typename Container::value_type>
77 template <typename Container>
78 struct container_value<Container const> : container_value<Container> {};
80 // There is no single container value for fusion maps, but because output
81 // of this metafunc is used to check wheter parser's attribute can be
82 // saved to container, we simply return whole fusion::map as is
83 // so that check can be done in traits::is_substitute specialisation
85 struct container_value<T
86 , typename enable_if<typename mpl::eval_if <
87 fusion::traits::is_sequence<T>
88 , fusion::traits::is_associative<T>
89 , mpl::false_ >::type >::type>
90 : mpl::identity<T> {};
93 struct container_value<unused_type> : mpl::identity<unused_type> {};
95 ///////////////////////////////////////////////////////////////////////////
96 template <typename Container, typename Enable = void>
97 struct container_iterator
98 : mpl::identity<typename Container::iterator> {};
100 template <typename Container>
101 struct container_iterator<Container const>
102 : mpl::identity<typename Container::const_iterator> {};
105 struct container_iterator<unused_type>
106 : mpl::identity<unused_type const*> {};
109 struct container_iterator<unused_type const>
110 : mpl::identity<unused_type const*> {};
112 ///////////////////////////////////////////////////////////////////////////
113 template <typename Container, typename T>
114 bool push_back(Container& c, T&& val);
116 template <typename Container, typename Enable = void>
117 struct push_back_container
119 template <typename T>
120 static bool call(Container& c, T&& val)
122 c.insert(c.end(), static_cast<T&&>(val));
127 template <typename Container, typename T>
128 inline bool push_back(Container& c, T&& val)
130 return push_back_container<Container>::call(c, static_cast<T&&>(val));
133 template <typename Container>
134 inline bool push_back(Container&, unused_type)
139 template <typename T>
140 inline bool push_back(unused_type, T&&)
145 inline bool push_back(unused_type, unused_type)
150 ///////////////////////////////////////////////////////////////////////////
151 template <typename Container, typename Iterator>
152 bool append(Container& c, Iterator first, Iterator last);
154 template <typename Container, typename Enable = void>
155 struct append_container
158 template <typename Iterator>
159 static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
161 c.insert(c.end(), first, last);
164 template <typename Iterator>
165 static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
167 c.insert(first, last);
171 template <typename Iterator>
172 static bool call(Container& c, Iterator first, Iterator last)
174 insert(c, first, last, is_associative<Container>{});
179 template <typename Container, typename Iterator>
180 inline bool append(Container& c, Iterator first, Iterator last)
182 return append_container<Container>::call(c, first, last);
185 template <typename Iterator>
186 inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
191 ///////////////////////////////////////////////////////////////////////////
192 template <typename Container, typename Enable = void>
193 struct is_empty_container
195 static bool call(Container const& c)
201 template <typename Container>
202 inline bool is_empty(Container const& c)
204 return is_empty_container<Container>::call(c);
207 inline bool is_empty(unused_type)
212 ///////////////////////////////////////////////////////////////////////////
213 template <typename Container, typename Enable = void>
214 struct begin_container
216 static typename container_iterator<Container>::type call(Container& c)
222 template <typename Container>
223 inline typename container_iterator<Container>::type
226 return begin_container<Container>::call(c);
229 inline unused_type const*
235 ///////////////////////////////////////////////////////////////////////////
236 template <typename Container, typename Enable = void>
239 static typename container_iterator<Container>::type call(Container& c)
245 template <typename Container>
246 inline typename container_iterator<Container>::type
249 return end_container<Container>::call(c);
252 inline unused_type const*
259 ///////////////////////////////////////////////////////////////////////////
260 template <typename Iterator, typename Enable = void>
261 struct deref_iterator
263 typedef typename std::iterator_traits<Iterator>::reference type;
264 static type call(Iterator& it)
270 template <typename Iterator>
271 typename deref_iterator<Iterator>::type
274 return deref_iterator<Iterator>::call(it);
278 deref(unused_type const*)
283 ///////////////////////////////////////////////////////////////////////////
284 template <typename Iterator, typename Enable = void>
287 static void call(Iterator& it)
293 template <typename Iterator>
294 void next(Iterator& it)
296 next_iterator<Iterator>::call(it);
299 inline void next(unused_type const*)
304 ///////////////////////////////////////////////////////////////////////////
305 template <typename Iterator, typename Enable = void>
306 struct compare_iterators
308 static bool call(Iterator const& it1, Iterator const& it2)
314 template <typename Iterator>
315 bool compare(Iterator& it1, Iterator& it2)
317 return compare_iterators<Iterator>::call(it1, it2);
320 inline bool compare(unused_type const*, unused_type const*)
325 ///////////////////////////////////////////////////////////////////////////
326 template <typename T>
327 struct build_container : mpl::identity<std::vector<T>> {};
329 template <typename T>
330 struct build_container<boost::fusion::deque<T> > : build_container<T> {};
333 struct build_container<unused_type> : mpl::identity<unused_type> {};
336 struct build_container<char> : mpl::identity<std::string> {};