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/tti/has_type.hpp>
16 #include <boost/mpl/identity.hpp>
23 namespace boost { namespace spirit { namespace x3 { namespace traits
25 ///////////////////////////////////////////////////////////////////////////
26 // This file contains some container utils for stl containers.
27 ///////////////////////////////////////////////////////////////////////////
31 BOOST_TTI_HAS_TYPE(value_type)
32 BOOST_TTI_HAS_TYPE(iterator)
33 BOOST_TTI_HAS_TYPE(size_type)
34 BOOST_TTI_HAS_TYPE(reference)
35 BOOST_TTI_HAS_TYPE(key_type)
39 using is_container = mpl::bool_<
40 detail::has_type_value_type<T>::value &&
41 detail::has_type_iterator<T>::value &&
42 detail::has_type_size_type<T>::value &&
43 detail::has_type_reference<T>::value>;
46 using is_associative = mpl::bool_<
47 detail::has_type_key_type<T>::value>;
49 template<typename T, typename Enable = void>
50 struct is_reservable : mpl::false_ {};
53 struct is_reservable<T, decltype(std::declval<T&>().reserve(0))>
56 ///////////////////////////////////////////////////////////////////////////
60 struct remove_value_const : mpl::identity<T> {};
63 struct remove_value_const<T const> : remove_value_const<T> {};
65 template <typename F, typename S>
66 struct remove_value_const<std::pair<F, S>>
68 typedef typename remove_value_const<F>::type first_type;
69 typedef typename remove_value_const<S>::type second_type;
70 typedef std::pair<first_type, second_type> type;
74 ///////////////////////////////////////////////////////////////////////
75 template <typename Container, typename Enable = void>
76 struct container_value
77 : detail::remove_value_const<typename Container::value_type>
80 template <typename Container>
81 struct container_value<Container const> : container_value<Container> {};
83 // There is no single container value for fusion maps, but because output
84 // of this metafunc is used to check wheter parser's attribute can be
85 // saved to container, we simply return whole fusion::map as is
86 // so that check can be done in traits::is_substitute specialisation
88 struct container_value<T
89 , typename enable_if<typename mpl::eval_if <
90 fusion::traits::is_sequence<T>
91 , fusion::traits::is_associative<T>
92 , mpl::false_ >::type >::type>
93 : mpl::identity<T> {};
96 struct container_value<unused_type> : mpl::identity<unused_type> {};
98 ///////////////////////////////////////////////////////////////////////////
99 template <typename Container, typename Enable = void>
100 struct container_iterator
101 : mpl::identity<typename Container::iterator> {};
103 template <typename Container>
104 struct container_iterator<Container const>
105 : mpl::identity<typename Container::const_iterator> {};
108 struct container_iterator<unused_type>
109 : mpl::identity<unused_type const*> {};
112 struct container_iterator<unused_type const>
113 : mpl::identity<unused_type const*> {};
115 ///////////////////////////////////////////////////////////////////////////
116 template <typename Container, typename T>
117 bool push_back(Container& c, T&& val);
119 template <typename Container, typename Enable = void>
120 struct push_back_container
122 template <typename T>
123 static bool call(Container& c, T&& val)
125 c.insert(c.end(), static_cast<T&&>(val));
130 template <typename Container, typename T>
131 inline bool push_back(Container& c, T&& val)
133 return push_back_container<Container>::call(c, static_cast<T&&>(val));
136 template <typename Container>
137 inline bool push_back(Container&, unused_type)
142 template <typename T>
143 inline bool push_back(unused_type, T&&)
148 inline bool push_back(unused_type, unused_type)
153 ///////////////////////////////////////////////////////////////////////////
154 template <typename Container, typename Iterator>
155 bool append(Container& c, Iterator first, Iterator last);
157 template <typename Container, typename Enable = void>
158 struct append_container
161 template <typename Iterator>
162 static void reserve(Container& /* c */, Iterator /* first */, Iterator /* last */, mpl::false_)
164 // Not all containers have "reserve"
167 template <typename Iterator>
168 static void reserve(Container& c, Iterator first, Iterator last, mpl::true_)
170 c.reserve(c.size() + std::distance(first, last));
173 template <typename Iterator>
174 static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
176 c.insert(c.end(), first, last);
179 template <typename Iterator>
180 static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
182 c.insert(first, last);
186 template <typename Iterator>
187 static bool call(Container& c, Iterator first, Iterator last)
189 reserve(c, first, last, is_reservable<Container>{});
190 insert(c, first, last, is_associative<Container>{});
195 template <typename Container, typename Iterator>
196 inline bool append(Container& c, Iterator first, Iterator last)
198 return append_container<Container>::call(c, first, last);
201 template <typename Iterator>
202 inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
207 ///////////////////////////////////////////////////////////////////////////
208 template <typename Container, typename Enable = void>
209 struct is_empty_container
211 static bool call(Container const& c)
217 template <typename Container>
218 inline bool is_empty(Container const& c)
220 return is_empty_container<Container>::call(c);
223 inline bool is_empty(unused_type)
228 ///////////////////////////////////////////////////////////////////////////
229 template <typename Container, typename Enable = void>
230 struct begin_container
232 static typename container_iterator<Container>::type call(Container& c)
238 template <typename Container>
239 inline typename container_iterator<Container>::type
242 return begin_container<Container>::call(c);
245 inline unused_type const*
251 ///////////////////////////////////////////////////////////////////////////
252 template <typename Container, typename Enable = void>
255 static typename container_iterator<Container>::type call(Container& c)
261 template <typename Container>
262 inline typename container_iterator<Container>::type
265 return end_container<Container>::call(c);
268 inline unused_type const*
275 ///////////////////////////////////////////////////////////////////////////
276 template <typename Iterator, typename Enable = void>
277 struct deref_iterator
279 typedef typename std::iterator_traits<Iterator>::reference type;
280 static type call(Iterator& it)
286 template <typename Iterator>
287 typename deref_iterator<Iterator>::type
290 return deref_iterator<Iterator>::call(it);
294 deref(unused_type const*)
299 ///////////////////////////////////////////////////////////////////////////
300 template <typename Iterator, typename Enable = void>
303 static void call(Iterator& it)
309 template <typename Iterator>
310 void next(Iterator& it)
312 next_iterator<Iterator>::call(it);
315 inline void next(unused_type const*)
320 ///////////////////////////////////////////////////////////////////////////
321 template <typename Iterator, typename Enable = void>
322 struct compare_iterators
324 static bool call(Iterator const& it1, Iterator const& it2)
330 template <typename Iterator>
331 bool compare(Iterator& it1, Iterator& it2)
333 return compare_iterators<Iterator>::call(it1, it2);
336 inline bool compare(unused_type const*, unused_type const*)
341 ///////////////////////////////////////////////////////////////////////////
342 template <typename T>
343 struct build_container : mpl::identity<std::vector<T>> {};
345 template <typename T>
346 struct build_container<boost::fusion::deque<T> > : build_container<T> {};
349 struct build_container<unused_type> : mpl::identity<unused_type> {};
352 struct build_container<char> : mpl::identity<std::string> {};