container_traits.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. http://spirit.sourceforge.net/
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM)
  9. #define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM
  10. #include <boost/fusion/support/category_of.hpp>
  11. #include <boost/spirit/home/x3/support/unused.hpp>
  12. #include <boost/fusion/include/deque.hpp>
  13. #include <boost/mpl/identity.hpp>
  14. #include <boost/type_traits/make_void.hpp>
  15. #include <vector>
  16. #include <string>
  17. #include <iterator>
  18. #include <algorithm>
  19. namespace boost { namespace spirit { namespace x3 { namespace traits
  20. {
  21. ///////////////////////////////////////////////////////////////////////////
  22. // This file contains some container utils for stl containers.
  23. ///////////////////////////////////////////////////////////////////////////
  24. namespace detail
  25. {
  26. template <typename T, typename Enabler = void>
  27. struct is_container_impl : mpl::false_ {};
  28. template <typename T>
  29. struct is_container_impl<T, void_t<
  30. typename T::value_type, typename T::iterator,
  31. typename T::size_type, typename T::reference> > : mpl::true_ {};
  32. template <typename T, typename Enabler = void>
  33. struct is_associative_impl : mpl::false_ {};
  34. template <typename T>
  35. struct is_associative_impl<T, void_t<typename T::key_type>>
  36. : mpl::true_ {};
  37. }
  38. template <typename T>
  39. using is_container = typename detail::is_container_impl<T>::type;
  40. template <typename T>
  41. using is_associative = typename detail::is_associative_impl<T>::type;
  42. ///////////////////////////////////////////////////////////////////////////
  43. namespace detail
  44. {
  45. template <typename T>
  46. struct remove_value_const : mpl::identity<T> {};
  47. template <typename T>
  48. struct remove_value_const<T const> : remove_value_const<T> {};
  49. template <typename F, typename S>
  50. struct remove_value_const<std::pair<F, S>>
  51. {
  52. typedef typename remove_value_const<F>::type first_type;
  53. typedef typename remove_value_const<S>::type second_type;
  54. typedef std::pair<first_type, second_type> type;
  55. };
  56. }
  57. ///////////////////////////////////////////////////////////////////////
  58. template <typename Container, typename Enable = void>
  59. struct container_value
  60. : detail::remove_value_const<typename Container::value_type>
  61. {};
  62. template <typename Container>
  63. struct container_value<Container const> : container_value<Container> {};
  64. // There is no single container value for fusion maps, but because output
  65. // of this metafunc is used to check wheter parser's attribute can be
  66. // saved to container, we simply return whole fusion::map as is
  67. // so that check can be done in traits::is_substitute specialisation
  68. template <typename T>
  69. struct container_value<T
  70. , typename enable_if<typename mpl::eval_if <
  71. fusion::traits::is_sequence<T>
  72. , fusion::traits::is_associative<T>
  73. , mpl::false_ >::type >::type>
  74. : mpl::identity<T> {};
  75. template <>
  76. struct container_value<unused_type> : mpl::identity<unused_type> {};
  77. ///////////////////////////////////////////////////////////////////////////
  78. template <typename Container, typename Enable = void>
  79. struct container_iterator
  80. : mpl::identity<typename Container::iterator> {};
  81. template <typename Container>
  82. struct container_iterator<Container const>
  83. : mpl::identity<typename Container::const_iterator> {};
  84. template <>
  85. struct container_iterator<unused_type>
  86. : mpl::identity<unused_type const*> {};
  87. template <>
  88. struct container_iterator<unused_type const>
  89. : mpl::identity<unused_type const*> {};
  90. ///////////////////////////////////////////////////////////////////////////
  91. template <typename Container, typename T>
  92. bool push_back(Container& c, T&& val);
  93. template <typename Container, typename Enable = void>
  94. struct push_back_container
  95. {
  96. template <typename T>
  97. static bool call(Container& c, T&& val)
  98. {
  99. c.insert(c.end(), static_cast<T&&>(val));
  100. return true;
  101. }
  102. };
  103. template <typename Container, typename T>
  104. inline bool push_back(Container& c, T&& val)
  105. {
  106. return push_back_container<Container>::call(c, static_cast<T&&>(val));
  107. }
  108. template <typename Container>
  109. inline bool push_back(Container&, unused_type)
  110. {
  111. return true;
  112. }
  113. template <typename T>
  114. inline bool push_back(unused_type, T&&)
  115. {
  116. return true;
  117. }
  118. inline bool push_back(unused_type, unused_type)
  119. {
  120. return true;
  121. }
  122. ///////////////////////////////////////////////////////////////////////////
  123. template <typename Container, typename Iterator>
  124. bool append(Container& c, Iterator first, Iterator last);
  125. template <typename Container, typename Enable = void>
  126. struct append_container
  127. {
  128. private:
  129. template <typename Iterator>
  130. static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
  131. {
  132. c.insert(c.end(), first, last);
  133. }
  134. template <typename Iterator>
  135. static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
  136. {
  137. c.insert(first, last);
  138. }
  139. public:
  140. template <typename Iterator>
  141. static bool call(Container& c, Iterator first, Iterator last)
  142. {
  143. insert(c, first, last, is_associative<Container>{});
  144. return true;
  145. }
  146. };
  147. template <typename Container, typename Iterator>
  148. inline bool append(Container& c, Iterator first, Iterator last)
  149. {
  150. return append_container<Container>::call(c, first, last);
  151. }
  152. template <typename Iterator>
  153. inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
  154. {
  155. return true;
  156. }
  157. ///////////////////////////////////////////////////////////////////////////
  158. template <typename Container, typename Enable = void>
  159. struct is_empty_container
  160. {
  161. static bool call(Container const& c)
  162. {
  163. return c.empty();
  164. }
  165. };
  166. template <typename Container>
  167. inline bool is_empty(Container const& c)
  168. {
  169. return is_empty_container<Container>::call(c);
  170. }
  171. inline bool is_empty(unused_type)
  172. {
  173. return true;
  174. }
  175. ///////////////////////////////////////////////////////////////////////////
  176. template <typename Container, typename Enable = void>
  177. struct begin_container
  178. {
  179. static typename container_iterator<Container>::type call(Container& c)
  180. {
  181. return c.begin();
  182. }
  183. };
  184. template <typename Container>
  185. inline typename container_iterator<Container>::type
  186. begin(Container& c)
  187. {
  188. return begin_container<Container>::call(c);
  189. }
  190. inline unused_type const*
  191. begin(unused_type)
  192. {
  193. return &unused;
  194. }
  195. ///////////////////////////////////////////////////////////////////////////
  196. template <typename Container, typename Enable = void>
  197. struct end_container
  198. {
  199. static typename container_iterator<Container>::type call(Container& c)
  200. {
  201. return c.end();
  202. }
  203. };
  204. template <typename Container>
  205. inline typename container_iterator<Container>::type
  206. end(Container& c)
  207. {
  208. return end_container<Container>::call(c);
  209. }
  210. inline unused_type const*
  211. end(unused_type)
  212. {
  213. return &unused;
  214. }
  215. ///////////////////////////////////////////////////////////////////////////
  216. template <typename Iterator, typename Enable = void>
  217. struct deref_iterator
  218. {
  219. typedef typename std::iterator_traits<Iterator>::reference type;
  220. static type call(Iterator& it)
  221. {
  222. return *it;
  223. }
  224. };
  225. template <typename Iterator>
  226. typename deref_iterator<Iterator>::type
  227. deref(Iterator& it)
  228. {
  229. return deref_iterator<Iterator>::call(it);
  230. }
  231. inline unused_type
  232. deref(unused_type const*)
  233. {
  234. return unused;
  235. }
  236. ///////////////////////////////////////////////////////////////////////////
  237. template <typename Iterator, typename Enable = void>
  238. struct next_iterator
  239. {
  240. static void call(Iterator& it)
  241. {
  242. ++it;
  243. }
  244. };
  245. template <typename Iterator>
  246. void next(Iterator& it)
  247. {
  248. next_iterator<Iterator>::call(it);
  249. }
  250. inline void next(unused_type const*)
  251. {
  252. // do nothing
  253. }
  254. ///////////////////////////////////////////////////////////////////////////
  255. template <typename Iterator, typename Enable = void>
  256. struct compare_iterators
  257. {
  258. static bool call(Iterator const& it1, Iterator const& it2)
  259. {
  260. return it1 == it2;
  261. }
  262. };
  263. template <typename Iterator>
  264. bool compare(Iterator& it1, Iterator& it2)
  265. {
  266. return compare_iterators<Iterator>::call(it1, it2);
  267. }
  268. inline bool compare(unused_type const*, unused_type const*)
  269. {
  270. return false;
  271. }
  272. ///////////////////////////////////////////////////////////////////////////
  273. template <typename T>
  274. struct build_container : mpl::identity<std::vector<T>> {};
  275. template <typename T>
  276. struct build_container<boost::fusion::deque<T> > : build_container<T> {};
  277. template <>
  278. struct build_container<unused_type> : mpl::identity<unused_type> {};
  279. template <>
  280. struct build_container<char> : mpl::identity<std::string> {};
  281. }}}}
  282. #endif