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