vector.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. assign(std::forward<Sequence>(seq), detail::index_sequence<I...>());
  195. }
  196. template <typename Sequence>
  197. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  198. void
  199. assign(Sequence&&, detail::index_sequence<>) {}
  200. template <typename Sequence, std::size_t N, std::size_t ...M>
  201. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  202. void
  203. assign(Sequence&& seq, detail::index_sequence<N, M...>)
  204. {
  205. at_impl(mpl::int_<N>()) = vector_detail::forward_at_c<N>(seq);
  206. assign(std::forward<Sequence>(seq), detail::index_sequence<M...>());
  207. }
  208. private:
  209. template <std::size_t J>
  210. using store_at = decltype(store_at_impl<J>(static_cast<vector_data*>(nullptr)));
  211. public:
  212. template <typename J>
  213. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  214. typename store_at<J::value>::elem_type& at_impl(J)
  215. {
  216. return store_at<J::value>::elem;
  217. }
  218. template <typename J>
  219. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  220. typename store_at<J::value>::elem_type const& at_impl(J) const
  221. {
  222. return store_at<J::value>::elem;
  223. }
  224. };
  225. } // namespace boost::fusion::vector_detail
  226. template <typename... T>
  227. struct vector
  228. : vector_detail::vector_data<
  229. typename detail::make_index_sequence<sizeof...(T)>::type
  230. , T...
  231. >
  232. {
  233. typedef vector_detail::vector_data<
  234. typename detail::make_index_sequence<sizeof...(T)>::type
  235. , T...
  236. > base;
  237. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  238. BOOST_DEFAULTED_FUNCTION(vector(), {})
  239. template <
  240. typename... U
  241. , typename = typename boost::enable_if_c<(
  242. sizeof...(U) >= 1 &&
  243. fusion::detail::and_<is_convertible<U, T>...>::value &&
  244. !fusion::detail::and_<
  245. is_base_of<vector, typename remove_reference<U>::type>...
  246. >::value
  247. )>::type
  248. >
  249. // XXX: constexpr become error due to pull-request #79, booooo!!
  250. // In the (near) future release, should be fixed.
  251. /* BOOST_CONSTEXPR */ BOOST_FUSION_GPU_ENABLED
  252. explicit vector(U&&... u)
  253. : base(vector_detail::each_elem(), std::forward<U>(u)...)
  254. {}
  255. template <
  256. typename Sequence
  257. , typename = typename boost::enable_if_c<
  258. vector_detail::is_longer_sequence<
  259. typename remove_reference<Sequence>::type, sizeof...(T)
  260. >::value
  261. >::type
  262. >
  263. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  264. vector(Sequence&& seq)
  265. : base(vector_detail::each_elem(), std::forward<Sequence>(seq))
  266. {}
  267. template <typename Sequence>
  268. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  269. vector&
  270. operator=(Sequence&& rhs)
  271. {
  272. base::assign_sequence(std::forward<Sequence>(rhs));
  273. return *this;
  274. }
  275. };
  276. }}
  277. #endif
  278. #endif