vector.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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. T elem;
  150. };
  151. template <typename I, typename ...T>
  152. struct vector_data;
  153. template <std::size_t ...I, typename ...T>
  154. struct vector_data<detail::index_sequence<I...>, T...>
  155. : store<I, T>...
  156. , sequence_base<vector_data<detail::index_sequence<I...>, T...> >
  157. {
  158. typedef vector_tag fusion_tag;
  159. typedef fusion_sequence_tag tag; // this gets picked up by MPL
  160. typedef mpl::false_ is_view;
  161. typedef random_access_traversal_tag category;
  162. typedef mpl::int_<sizeof...(T)> size;
  163. typedef vector<T...> type_sequence;
  164. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  165. BOOST_DEFAULTED_FUNCTION(vector_data(), {})
  166. template <
  167. typename Sequence
  168. , typename Sequence_ = typename remove_reference<Sequence>::type
  169. , typename = typename boost::enable_if<
  170. can_convert<vector_data, Sequence, Sequence_, sizeof...(I)>
  171. >::type
  172. >
  173. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  174. explicit
  175. vector_data(each_elem, Sequence&& rhs)
  176. : store<I, T>(forward_at_c<I>(std::forward<Sequence>(rhs)))...
  177. {}
  178. template <typename ...U>
  179. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  180. explicit
  181. vector_data(each_elem, U&&... var)
  182. : store<I, T>(std::forward<U>(var))...
  183. {}
  184. template <typename Sequence>
  185. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  186. void
  187. assign_sequence(Sequence&& seq)
  188. {
  189. assign(std::forward<Sequence>(seq), detail::index_sequence<I...>());
  190. }
  191. template <typename Sequence>
  192. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  193. void
  194. assign(Sequence&&, detail::index_sequence<>) {}
  195. template <typename Sequence, std::size_t N, std::size_t ...M>
  196. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  197. void
  198. assign(Sequence&& seq, detail::index_sequence<N, M...>)
  199. {
  200. at_impl(mpl::int_<N>()) = vector_detail::forward_at_c<N>(seq);
  201. assign(std::forward<Sequence>(seq), detail::index_sequence<M...>());
  202. }
  203. template <std::size_t N, typename U>
  204. static BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  205. U& at_detail(store<N, U>* this_)
  206. {
  207. return this_->elem;
  208. }
  209. template <std::size_t N, typename U>
  210. static BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  211. U const& at_detail(store<N, U> const* this_)
  212. {
  213. return this_->elem;
  214. }
  215. template <typename J>
  216. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  217. auto at_impl(J) -> decltype(at_detail<J::value>(&std::declval<vector_data&>()))
  218. {
  219. return at_detail<J::value>(this);
  220. }
  221. template <typename J>
  222. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  223. auto at_impl(J) const -> decltype(at_detail<J::value>(&std::declval<vector_data const&>()))
  224. {
  225. return at_detail<J::value>(this);
  226. }
  227. };
  228. } // namespace boost::fusion::vector_detail
  229. template <typename... T>
  230. struct vector
  231. : vector_detail::vector_data<
  232. typename detail::make_index_sequence<sizeof...(T)>::type
  233. , T...
  234. >
  235. {
  236. typedef vector_detail::vector_data<
  237. typename detail::make_index_sequence<sizeof...(T)>::type
  238. , T...
  239. > base;
  240. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  241. BOOST_DEFAULTED_FUNCTION(vector(), {})
  242. template <
  243. typename... U
  244. , typename = typename boost::enable_if_c<(
  245. sizeof...(U) >= 1 &&
  246. fusion::detail::and_<is_convertible<U, T>...>::value &&
  247. !fusion::detail::and_<
  248. is_base_of<vector, typename remove_reference<U>::type>...
  249. >::value
  250. )>::type
  251. >
  252. // XXX: constexpr become error due to pull-request #79, booooo!!
  253. // In the (near) future release, should be fixed.
  254. /* BOOST_CONSTEXPR */ BOOST_FUSION_GPU_ENABLED
  255. explicit vector(U&&... u)
  256. : base(vector_detail::each_elem(), std::forward<U>(u)...)
  257. {}
  258. template <
  259. typename Sequence
  260. , typename = typename boost::enable_if_c<
  261. vector_detail::is_longer_sequence<
  262. typename remove_reference<Sequence>::type, sizeof...(T)
  263. >::value
  264. >::type
  265. >
  266. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  267. vector(Sequence&& seq)
  268. : base(vector_detail::each_elem(), std::forward<Sequence>(seq))
  269. {}
  270. template <typename Sequence>
  271. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  272. vector&
  273. operator=(Sequence&& rhs)
  274. {
  275. base::assign_sequence(std::forward<Sequence>(rhs));
  276. return *this;
  277. }
  278. };
  279. }}
  280. #endif
  281. #endif