container_traits.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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/tti/has_type.hpp>
  14. #include <boost/mpl/identity.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. BOOST_TTI_HAS_TYPE(value_type)
  27. BOOST_TTI_HAS_TYPE(iterator)
  28. BOOST_TTI_HAS_TYPE(size_type)
  29. BOOST_TTI_HAS_TYPE(reference)
  30. BOOST_TTI_HAS_TYPE(key_type)
  31. }
  32. template <typename T>
  33. using is_container = mpl::bool_<
  34. detail::has_type_value_type<T>::value &&
  35. detail::has_type_iterator<T>::value &&
  36. detail::has_type_size_type<T>::value &&
  37. detail::has_type_reference<T>::value>;
  38. template <typename T>
  39. using is_associative = mpl::bool_<
  40. detail::has_type_key_type<T>::value>;
  41. template<typename T, typename Enable = void>
  42. struct is_reservable : mpl::false_ {};
  43. template<typename T>
  44. struct is_reservable<T, decltype(std::declval<T&>().reserve(0))>
  45. : mpl::true_ {};
  46. ///////////////////////////////////////////////////////////////////////////
  47. namespace detail
  48. {
  49. template <typename T>
  50. struct remove_value_const : mpl::identity<T> {};
  51. template <typename T>
  52. struct remove_value_const<T const> : remove_value_const<T> {};
  53. template <typename F, typename S>
  54. struct remove_value_const<std::pair<F, S>>
  55. {
  56. typedef typename remove_value_const<F>::type first_type;
  57. typedef typename remove_value_const<S>::type second_type;
  58. typedef std::pair<first_type, second_type> type;
  59. };
  60. }
  61. ///////////////////////////////////////////////////////////////////////
  62. template <typename Container, typename Enable = void>
  63. struct container_value
  64. : detail::remove_value_const<typename Container::value_type>
  65. {};
  66. template <typename Container>
  67. struct container_value<Container const> : container_value<Container> {};
  68. // There is no single container value for fusion maps, but because output
  69. // of this metafunc is used to check wheter parser's attribute can be
  70. // saved to container, we simply return whole fusion::map as is
  71. // so that check can be done in traits::is_substitute specialisation
  72. template <typename T>
  73. struct container_value<T
  74. , typename enable_if<typename mpl::eval_if <
  75. fusion::traits::is_sequence<T>
  76. , fusion::traits::is_associative<T>
  77. , mpl::false_ >::type >::type>
  78. : mpl::identity<T> {};
  79. template <>
  80. struct container_value<unused_type> : mpl::identity<unused_type> {};
  81. ///////////////////////////////////////////////////////////////////////////
  82. template <typename Container, typename Enable = void>
  83. struct container_iterator
  84. : mpl::identity<typename Container::iterator> {};
  85. template <typename Container>
  86. struct container_iterator<Container const>
  87. : mpl::identity<typename Container::const_iterator> {};
  88. template <>
  89. struct container_iterator<unused_type>
  90. : mpl::identity<unused_type const*> {};
  91. template <>
  92. struct container_iterator<unused_type const>
  93. : mpl::identity<unused_type const*> {};
  94. ///////////////////////////////////////////////////////////////////////////
  95. template <typename Container, typename T>
  96. bool push_back(Container& c, T&& val);
  97. template <typename Container, typename Enable = void>
  98. struct push_back_container
  99. {
  100. template <typename T>
  101. static bool call(Container& c, T&& val)
  102. {
  103. c.insert(c.end(), static_cast<T&&>(val));
  104. return true;
  105. }
  106. };
  107. template <typename Container, typename T>
  108. inline bool push_back(Container& c, T&& val)
  109. {
  110. return push_back_container<Container>::call(c, static_cast<T&&>(val));
  111. }
  112. template <typename Container>
  113. inline bool push_back(Container&, unused_type)
  114. {
  115. return true;
  116. }
  117. template <typename T>
  118. inline bool push_back(unused_type, T&&)
  119. {
  120. return true;
  121. }
  122. inline bool push_back(unused_type, unused_type)
  123. {
  124. return true;
  125. }
  126. ///////////////////////////////////////////////////////////////////////////
  127. template <typename Container, typename Iterator>
  128. bool append(Container& c, Iterator first, Iterator last);
  129. template <typename Container, typename Enable = void>
  130. struct append_container
  131. {
  132. private:
  133. template <typename Iterator>
  134. static void reserve(Container& /* c */, Iterator /* first */, Iterator /* last */, mpl::false_)
  135. {
  136. // Not all containers have "reserve"
  137. }
  138. template <typename Iterator>
  139. static void reserve(Container& c, Iterator first, Iterator last, mpl::true_)
  140. {
  141. c.reserve(c.size() + std::distance(first, last));
  142. }
  143. template <typename Iterator>
  144. static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
  145. {
  146. c.insert(c.end(), first, last);
  147. }
  148. template <typename Iterator>
  149. static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
  150. {
  151. c.insert(first, last);
  152. }
  153. public:
  154. template <typename Iterator>
  155. static bool call(Container& c, Iterator first, Iterator last)
  156. {
  157. reserve(c, first, last, is_reservable<Container>{});
  158. insert(c, first, last, is_associative<Container>{});
  159. return true;
  160. }
  161. };
  162. template <typename Container, typename Iterator>
  163. inline bool append(Container& c, Iterator first, Iterator last)
  164. {
  165. return append_container<Container>::call(c, first, last);
  166. }
  167. template <typename Iterator>
  168. inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
  169. {
  170. return true;
  171. }
  172. ///////////////////////////////////////////////////////////////////////////
  173. template <typename Container, typename Enable = void>
  174. struct is_empty_container
  175. {
  176. static bool call(Container const& c)
  177. {
  178. return c.empty();
  179. }
  180. };
  181. template <typename Container>
  182. inline bool is_empty(Container const& c)
  183. {
  184. return is_empty_container<Container>::call(c);
  185. }
  186. inline bool is_empty(unused_type)
  187. {
  188. return true;
  189. }
  190. ///////////////////////////////////////////////////////////////////////////
  191. template <typename Container, typename Enable = void>
  192. struct begin_container
  193. {
  194. static typename container_iterator<Container>::type call(Container& c)
  195. {
  196. return c.begin();
  197. }
  198. };
  199. template <typename Container>
  200. inline typename container_iterator<Container>::type
  201. begin(Container& c)
  202. {
  203. return begin_container<Container>::call(c);
  204. }
  205. inline unused_type const*
  206. begin(unused_type)
  207. {
  208. return &unused;
  209. }
  210. ///////////////////////////////////////////////////////////////////////////
  211. template <typename Container, typename Enable = void>
  212. struct end_container
  213. {
  214. static typename container_iterator<Container>::type call(Container& c)
  215. {
  216. return c.end();
  217. }
  218. };
  219. template <typename Container>
  220. inline typename container_iterator<Container>::type
  221. end(Container& c)
  222. {
  223. return end_container<Container>::call(c);
  224. }
  225. inline unused_type const*
  226. end(unused_type)
  227. {
  228. return &unused;
  229. }
  230. ///////////////////////////////////////////////////////////////////////////
  231. template <typename Iterator, typename Enable = void>
  232. struct deref_iterator
  233. {
  234. typedef typename std::iterator_traits<Iterator>::reference type;
  235. static type call(Iterator& it)
  236. {
  237. return *it;
  238. }
  239. };
  240. template <typename Iterator>
  241. typename deref_iterator<Iterator>::type
  242. deref(Iterator& it)
  243. {
  244. return deref_iterator<Iterator>::call(it);
  245. }
  246. inline unused_type
  247. deref(unused_type const*)
  248. {
  249. return unused;
  250. }
  251. ///////////////////////////////////////////////////////////////////////////
  252. template <typename Iterator, typename Enable = void>
  253. struct next_iterator
  254. {
  255. static void call(Iterator& it)
  256. {
  257. ++it;
  258. }
  259. };
  260. template <typename Iterator>
  261. void next(Iterator& it)
  262. {
  263. next_iterator<Iterator>::call(it);
  264. }
  265. inline void next(unused_type const*)
  266. {
  267. // do nothing
  268. }
  269. ///////////////////////////////////////////////////////////////////////////
  270. template <typename Iterator, typename Enable = void>
  271. struct compare_iterators
  272. {
  273. static bool call(Iterator const& it1, Iterator const& it2)
  274. {
  275. return it1 == it2;
  276. }
  277. };
  278. template <typename Iterator>
  279. bool compare(Iterator& it1, Iterator& it2)
  280. {
  281. return compare_iterators<Iterator>::call(it1, it2);
  282. }
  283. inline bool compare(unused_type const*, unused_type const*)
  284. {
  285. return false;
  286. }
  287. ///////////////////////////////////////////////////////////////////////////
  288. template <typename T>
  289. struct build_container : mpl::identity<std::vector<T>> {};
  290. template <typename T>
  291. struct build_container<boost::fusion::deque<T> > : build_container<T> {};
  292. template <>
  293. struct build_container<unused_type> : mpl::identity<unused_type> {};
  294. template <>
  295. struct build_container<char> : mpl::identity<std::string> {};
  296. }}}}
  297. #endif