vector.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*=============================================================================
  2. Copyright (c) 2014-2015 Kohei Takahashi
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #ifndef FUSION_VECTOR_11052014_1625
  7. #define FUSION_VECTOR_11052014_1625
  8. #include <boost/config.hpp>
  9. #include <boost/fusion/support/config.hpp>
  10. #include <boost/fusion/container/vector/detail/config.hpp>
  11. #include <boost/fusion/container/vector/vector_fwd.hpp>
  12. ///////////////////////////////////////////////////////////////////////////////
  13. // Without variadics, we will use the PP version
  14. ///////////////////////////////////////////////////////////////////////////////
  15. #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
  16. # include <boost/fusion/container/vector/detail/cpp03/vector.hpp>
  17. #else
  18. ///////////////////////////////////////////////////////////////////////////////
  19. // C++11 interface
  20. ///////////////////////////////////////////////////////////////////////////////
  21. #include <boost/fusion/support/sequence_base.hpp>
  22. #include <boost/fusion/support/is_sequence.hpp>
  23. #include <boost/fusion/support/detail/and.hpp>
  24. #include <boost/fusion/support/detail/index_sequence.hpp>
  25. #include <boost/fusion/container/vector/detail/at_impl.hpp>
  26. #include <boost/fusion/container/vector/detail/value_at_impl.hpp>
  27. #include <boost/fusion/container/vector/detail/begin_impl.hpp>
  28. #include <boost/fusion/container/vector/detail/end_impl.hpp>
  29. #include <boost/fusion/sequence/intrinsic/begin.hpp>
  30. #include <boost/fusion/sequence/intrinsic/size.hpp>
  31. #include <boost/fusion/iterator/advance.hpp>
  32. #include <boost/fusion/iterator/deref.hpp>
  33. #include <boost/core/enable_if.hpp>
  34. #include <boost/mpl/int.hpp>
  35. #include <boost/type_traits/integral_constant.hpp>
  36. #include <boost/type_traits/is_base_of.hpp>
  37. #include <boost/type_traits/is_convertible.hpp>
  38. #include <boost/type_traits/remove_reference.hpp>
  39. #include <cstddef>
  40. #include <utility>
  41. namespace boost { namespace fusion
  42. {
  43. struct vector_tag;
  44. struct random_access_traversal_tag;
  45. namespace vector_detail
  46. {
  47. struct each_elem {};
  48. template <
  49. typename This, typename T, typename T_, std::size_t Size, bool IsSeq
  50. >
  51. struct can_convert_impl : false_type {};
  52. template <typename This, typename T, typename Sequence, std::size_t Size>
  53. struct can_convert_impl<This, T, Sequence, Size, true> : true_type {};
  54. template <typename This, typename Sequence, typename T>
  55. struct can_convert_impl<This, Sequence, T, 1, true>
  56. : integral_constant<
  57. bool
  58. , !is_convertible<
  59. Sequence
  60. , typename fusion::extension::value_at_impl<vector_tag>::
  61. template apply< This, mpl::int_<0> >::type
  62. >::value
  63. >
  64. {};
  65. template <typename This, typename T, typename T_, std::size_t Size>
  66. struct can_convert
  67. : can_convert_impl<
  68. This, T, T_, Size, traits::is_sequence<T_>::value
  69. >
  70. {};
  71. template <typename T, bool IsSeq, std::size_t Size>
  72. struct is_longer_sequence_impl : false_type {};
  73. template <typename Sequence, std::size_t Size>
  74. struct is_longer_sequence_impl<Sequence, true, Size>
  75. : integral_constant<
  76. bool, (fusion::result_of::size<Sequence>::value >= Size)
  77. >
  78. {};
  79. template<typename T, std::size_t Size>
  80. struct is_longer_sequence
  81. : is_longer_sequence_impl<T, traits::is_sequence<T>::value, Size>
  82. {};
  83. // forward_at_c allows to access Nth element even if ForwardSequence
  84. // since fusion::at_c requires RandomAccessSequence.
  85. namespace result_of
  86. {
  87. template <typename Sequence, int N>
  88. struct forward_at_c
  89. : fusion::result_of::deref<
  90. typename fusion::result_of::advance_c<
  91. typename fusion::result_of::begin<
  92. typename remove_reference<Sequence>::type
  93. >::type
  94. , N
  95. >::type
  96. >
  97. {};
  98. }
  99. template <int N, typename Sequence>
  100. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  101. inline typename result_of::forward_at_c<Sequence, N>::type
  102. forward_at_c(Sequence&& seq)
  103. {
  104. typedef typename
  105. result_of::forward_at_c<Sequence, N>::type
  106. result;
  107. return std::forward<result>(*advance_c<N>(begin(seq)));
  108. }
  109. // Object proxy since preserve object order
  110. template <std::size_t, typename T>
  111. struct store
  112. {
  113. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  114. store()
  115. : elem() // value-initialized explicitly
  116. {}
  117. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  118. store(store const& rhs)
  119. : elem(rhs.elem)
  120. {}
  121. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  122. store&
  123. operator=(store const& rhs)
  124. {
  125. elem = rhs.elem;
  126. return *this;
  127. }
  128. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  129. store(store&& rhs)
  130. : elem(static_cast<T&&>(rhs.elem))
  131. {}
  132. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  133. store&
  134. operator=(store&& rhs)
  135. {
  136. elem = static_cast<T&&>(rhs.elem);
  137. return *this;
  138. }
  139. template <
  140. typename U
  141. , typename = typename boost::disable_if<
  142. is_base_of<store, typename remove_reference<U>::type>
  143. >::type
  144. >
  145. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  146. store(U&& rhs)
  147. : elem(std::forward<U>(rhs))
  148. {}
  149. using elem_type = T;
  150. T elem;
  151. };
  152. // placed outside of vector_data due to GCC < 6 bug
  153. template <std::size_t J, typename U>
  154. static inline BOOST_FUSION_GPU_ENABLED
  155. store<J, U> store_at_impl(store<J, U>*);
  156. template <typename I, typename ...T>
  157. struct vector_data;
  158. template <std::size_t ...I, typename ...T>
  159. struct vector_data<detail::index_sequence<I...>, T...>
  160. : store<I, T>...
  161. , sequence_base<vector_data<detail::index_sequence<I...>, T...> >
  162. {
  163. typedef vector_tag fusion_tag;
  164. typedef fusion_sequence_tag tag; // this gets picked up by MPL
  165. typedef mpl::false_ is_view;
  166. typedef random_access_traversal_tag category;
  167. typedef mpl::int_<sizeof...(T)> size;
  168. typedef vector<T...> type_sequence;
  169. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  170. BOOST_DEFAULTED_FUNCTION(vector_data(), {})
  171. template <
  172. typename Sequence
  173. , typename Sequence_ = typename remove_reference<Sequence>::type
  174. , typename = typename boost::enable_if<
  175. can_convert<vector_data, Sequence, Sequence_, sizeof...(I)>
  176. >::type
  177. >
  178. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  179. explicit
  180. vector_data(each_elem, Sequence&& rhs)
  181. : store<I, T>(forward_at_c<I>(std::forward<Sequence>(rhs)))...
  182. {}
  183. template <typename ...U>
  184. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  185. explicit
  186. vector_data(each_elem, U&&... var)
  187. : store<I, T>(std::forward<U>(var))...
  188. {}
  189. template <typename Sequence>
  190. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  191. void
  192. assign_sequence(Sequence&& seq)
  193. {
  194. #ifndef BOOST_NO_CXX17_FOLD_EXPRESSIONS
  195. (void(store<I, T>::elem = vector_detail::forward_at_c<I>(static_cast<Sequence&&>(seq))), ...);
  196. #else
  197. int nofold[] = { (void(store<I, T>::elem = vector_detail::forward_at_c<I>(static_cast<Sequence&&>(seq))), 0)..., 0 };
  198. (void)nofold;
  199. #endif
  200. }
  201. private:
  202. template <std::size_t J>
  203. using store_at = decltype(store_at_impl<J>(static_cast<vector_data*>(nullptr)));
  204. public:
  205. template <typename J>
  206. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  207. typename store_at<J::value>::elem_type& at_impl(J)
  208. {
  209. return store_at<J::value>::elem;
  210. }
  211. template <typename J>
  212. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  213. typename store_at<J::value>::elem_type const& at_impl(J) const
  214. {
  215. return store_at<J::value>::elem;
  216. }
  217. };
  218. } // namespace boost::fusion::vector_detail
  219. template <typename... T>
  220. struct vector
  221. : vector_detail::vector_data<
  222. typename detail::make_index_sequence<sizeof...(T)>::type
  223. , T...
  224. >
  225. {
  226. typedef vector_detail::vector_data<
  227. typename detail::make_index_sequence<sizeof...(T)>::type
  228. , T...
  229. > base;
  230. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  231. BOOST_DEFAULTED_FUNCTION(vector(), {})
  232. template <
  233. typename... U
  234. , typename = typename boost::enable_if_c<(
  235. sizeof...(U) >= 1 &&
  236. fusion::detail::and_<is_convertible<U, T>...>::value &&
  237. !fusion::detail::and_<
  238. is_base_of<vector, typename remove_reference<U>::type>...
  239. >::value
  240. )>::type
  241. >
  242. // XXX: constexpr become error due to pull-request #79, booooo!!
  243. // In the (near) future release, should be fixed.
  244. /* BOOST_CONSTEXPR */ BOOST_FUSION_GPU_ENABLED
  245. explicit vector(U&&... u)
  246. : base(vector_detail::each_elem(), std::forward<U>(u)...)
  247. {}
  248. template <
  249. typename Sequence
  250. , typename = typename boost::enable_if_c<
  251. vector_detail::is_longer_sequence<
  252. typename remove_reference<Sequence>::type, sizeof...(T)
  253. >::value
  254. >::type
  255. >
  256. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  257. vector(Sequence&& seq)
  258. : base(vector_detail::each_elem(), std::forward<Sequence>(seq))
  259. {}
  260. template <typename Sequence>
  261. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  262. vector&
  263. operator=(Sequence&& rhs)
  264. {
  265. base::assign_sequence(std::forward<Sequence>(rhs));
  266. return *this;
  267. }
  268. };
  269. }}
  270. #endif
  271. #endif