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.get())
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.get();
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.get()))
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.get());
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             BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
getboost::fusion::vector_detail::store172             T      & get()       { return elem; }
173             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
getboost::fusion::vector_detail::store174             T const& get() const { return elem; }
175 
176             T elem;
177         };
178 
179         template <typename I, typename ...T>
180         struct vector_data;
181 
182         template <std::size_t ...I, typename ...T>
183         struct vector_data<detail::index_sequence<I...>, T...>
184             : store<I, T>...
185             , sequence_base<vector_data<detail::index_sequence<I...>, T...> >
186         {
187             typedef vector_tag                  fusion_tag;
188             typedef fusion_sequence_tag         tag; // this gets picked up by MPL
189             typedef mpl::false_                 is_view;
190             typedef random_access_traversal_tag category;
191             typedef mpl::int_<sizeof...(T)>     size;
192             typedef vector<T...>                type_sequence;
193 
194             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
vector_databoost::fusion::vector_detail::vector_data195             vector_data()
196             {}
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
vector_databoost::fusion::vector_detail::vector_data207             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             template <std::size_t N, typename U>
241             static BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
at_detailboost::fusion::vector_detail::vector_data242             auto at_detail(store<N, U>* this_) -> decltype(this_->get())
243             {
244                 return this_->get();
245             }
246 
247             template <std::size_t N, typename U>
248             static BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
at_detailboost::fusion::vector_detail::vector_data249             auto at_detail(store<N, U> const* this_) -> decltype(this_->get())
250             {
251                 return this_->get();
252             }
253 
254             template <typename J>
255             BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
at_implboost::fusion::vector_detail::vector_data256             auto at_impl(J) -> decltype(at_detail<J::value>(this))
257             {
258                 return at_detail<J::value>(this);
259             }
260 
261             template <typename J>
262             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
at_implboost::fusion::vector_detail::vector_data263             auto at_impl(J) const -> decltype(at_detail<J::value>(this))
264             {
265                 return at_detail<J::value>(this);
266             }
267 
268             template <std::size_t N, typename U>
269             static BOOST_FUSION_GPU_ENABLED
270             mpl::identity<U> value_at_impl(store<N, U>*);
271         };
272     } // namespace boost::fusion::vector_detail
273 
274     template <typename... T>
275     struct vector
276         : vector_detail::vector_data<
277               typename detail::make_index_sequence<sizeof...(T)>::type
278             , T...
279           >
280     {
281         typedef vector_detail::vector_data<
282             typename detail::make_index_sequence<sizeof...(T)>::type
283           , T...
284         > base;
285 
286         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
vectorboost::fusion::vector287         vector()
288         {}
289 
290         template <
291             typename... U
292           , typename = typename boost::enable_if_c<(
293                 sizeof...(U) >= 1 &&
294                 fusion::detail::and_<is_convertible<U, T>...>::value &&
295                 !fusion::detail::and_<
296                     is_base_of<vector, typename remove_reference<U>::type>...
297                 >::value
298             )>::type
299         >
300         // XXX: constexpr become error due to pull-request #79, booooo!!
301         //      In the (near) future release, should be fixed.
302         /* BOOST_CONSTEXPR */ BOOST_FUSION_GPU_ENABLED
vectorboost::fusion::vector303         explicit vector(U&&... u)
304             : base(vector_detail::each_elem(), std::forward<U>(u)...)
305         {}
306 
307         template <
308             typename Sequence
309           , typename Sequence_ = typename remove_reference<Sequence>::type
310           , typename = typename boost::enable_if_c<(
311                 !is_base_of<vector, Sequence_>::value &&
312                 vector_detail::is_longer_sequence<
313                     Sequence_, sizeof...(T)
314                 >::value
315             )>::type
316         >
317         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
vectorboost::fusion::vector318         vector(Sequence&& seq)
319             : base(vector_detail::each_elem(), std::forward<Sequence>(seq))
320         {}
321 
322         template <typename Sequence>
323         BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
324         vector&
operator =boost::fusion::vector325         operator=(Sequence&& rhs)
326         {
327             base::assign_sequence(std::forward<Sequence>(rhs));
328             return *this;
329         }
330     };
331 }}
332 
333 #endif
334 #endif
335 
336