Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:16

0001 /*=============================================================================
0002     Copyright (c) 2014 Paul Fultz II
0003     pack.h
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 
0008 #ifndef BOOST_HOF_GUARD_FUNCTION_PACK_H
0009 #define BOOST_HOF_GUARD_FUNCTION_PACK_H
0010 
0011 /// pack
0012 /// ====
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `pack` function returns a higher order function object that takes a
0018 /// function that will be passed the initial elements. The function object is
0019 /// a sequence that can be unpacked with `unpack_adaptor` as well. Also,
0020 /// `pack_join` can be used to join multiple packs together.
0021 /// 
0022 /// Synopsis
0023 /// --------
0024 /// 
0025 ///     // Decay everything before capturing
0026 ///     template<class... Ts>
0027 ///     constexpr auto pack(Ts&&... xs);
0028 /// 
0029 ///     // Capture lvalues by reference and rvalue reference by reference
0030 ///     template<class... Ts>
0031 ///     constexpr auto pack_forward(Ts&&... xs);
0032 /// 
0033 ///     // Capture lvalues by reference and rvalues by value.
0034 ///     template<class... Ts>
0035 ///     constexpr auto pack_basic(Ts&&... xs);
0036 /// 
0037 ///     // Join multiple packs together
0038 ///     template<class... Ts>
0039 ///     constexpr auto pack_join(Ts&&... xs);
0040 /// 
0041 /// Semantics
0042 /// ---------
0043 /// 
0044 ///     assert(pack(xs...)(f) == f(xs...));
0045 ///     assert(unpack(f)(pack(xs...)) == f(xs...));
0046 /// 
0047 ///     assert(pack_join(pack(xs...), pack(ys...)) == pack(xs..., ys...));
0048 /// 
0049 /// 
0050 /// Example
0051 /// -------
0052 /// 
0053 ///     #include <boost/hof.hpp>
0054 ///     #include <cassert>
0055 ///     using namespace boost::hof;
0056 /// 
0057 ///     struct sum
0058 ///     {
0059 ///         template<class T, class U>
0060 ///         T operator()(T x, U y) const
0061 ///         {
0062 ///             return x+y;
0063 ///         }
0064 ///     };
0065 /// 
0066 ///     int main() {
0067 ///         int r = pack(3, 2)(sum());
0068 ///         assert(r == 5);
0069 ///     }
0070 /// 
0071 /// See Also
0072 /// --------
0073 /// 
0074 /// * [unpack](unpack)
0075 /// 
0076 
0077 #include <boost/hof/detail/seq.hpp>
0078 #include <boost/hof/detail/delegate.hpp>
0079 #include <boost/hof/detail/remove_rvalue_reference.hpp>
0080 #include <boost/hof/detail/unwrap.hpp>
0081 #include <boost/hof/detail/static_const_var.hpp>
0082 #include <boost/hof/unpack_sequence.hpp>
0083 #include <boost/hof/returns.hpp>
0084 #include <boost/hof/alias.hpp>
0085 #include <boost/hof/decay.hpp>
0086 
0087 namespace boost { namespace hof { namespace detail {
0088 
0089 template<class...>
0090 struct pack_tag
0091 {};
0092 
0093 template<class T, class Tag>
0094 struct pack_holder
0095 : detail::alias_empty<T, Tag>
0096 {};
0097 
0098 template<class Seq, class... Ts>
0099 struct pack_base;
0100 
0101 template<class T>
0102 struct is_copyable
0103 : std::integral_constant<bool, (
0104     BOOST_HOF_IS_CONSTRUCTIBLE(T, const T&)
0105 )>
0106 {};
0107 
0108 template<class T>
0109 struct is_copyable<T&>
0110 : std::true_type
0111 {};
0112 
0113 template<class T>
0114 struct is_copyable<T&&>
0115 : std::true_type
0116 {};
0117 
0118 template<class T, class Tag, class X, class... Ts, typename std::enable_if<
0119     is_copyable<T>::value && !std::is_lvalue_reference<T>::value
0120 , int>::type = 0>
0121 constexpr T pack_get(X&& x, Ts&&... xs) noexcept(BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(T))
0122 {
0123     return static_cast<T>(boost::hof::alias_value<Tag, T>(BOOST_HOF_FORWARD(X)(x), xs...));
0124 }
0125 
0126 template<class T, class Tag, class X, class... Ts, typename std::enable_if<
0127     std::is_lvalue_reference<T>::value
0128 , int>::type = 0>
0129 constexpr T pack_get(X&& x, Ts&&... xs) noexcept
0130 {
0131     return boost::hof::alias_value<Tag, T>(x, xs...);
0132 }
0133 
0134 template<class T, class Tag, class X, class... Ts, typename std::enable_if<
0135     !is_copyable<T>::value
0136 , int>::type = 0>
0137 constexpr auto pack_get(X&& x, Ts&&... xs) BOOST_HOF_RETURNS
0138 (
0139     boost::hof::alias_value<Tag, T>(BOOST_HOF_FORWARD(X)(x), xs...)
0140 );
0141 
0142 #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) || defined(_MSC_VER)
0143 template<class... Ts>
0144 struct pack_holder_base
0145 : Ts::type...
0146 {
0147     template<class... Xs, class=typename std::enable_if<(sizeof...(Xs) == sizeof...(Ts))>::type>
0148     constexpr pack_holder_base(Xs&&... xs) 
0149     BOOST_HOF_NOEXCEPT(BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(typename Ts::type, Xs&&)))
0150     : Ts::type(BOOST_HOF_FORWARD(Xs)(xs))...
0151     {}
0152 #ifndef _MSC_VER
0153     // BOOST_HOF_INHERIT_DEFAULT(pack_holder_base, typename std::remove_cv<typename std::remove_reference<typename Ts::type>::type>::type...)
0154     BOOST_HOF_INHERIT_DEFAULT(pack_holder_base, typename Ts::type...)
0155 #endif
0156 };
0157 
0158 template<class T>
0159 struct pack_holder_base<T>
0160 : T::type
0161 {
0162     typedef typename T::type base;
0163     BOOST_HOF_INHERIT_CONSTRUCTOR(pack_holder_base, base);
0164 };
0165 
0166 template<class... Ts>
0167 struct pack_holder_builder
0168 {
0169     template<class T, std::size_t N>
0170     struct apply
0171     : pack_holder<T, pack_tag<seq<N>, Ts...>>
0172     {};
0173 };
0174 
0175 template<std::size_t... Ns, class... Ts>
0176 struct pack_base<seq<Ns...>, Ts...>
0177 : pack_holder_base<typename pack_holder_builder<Ts...>::template apply<Ts, Ns>...>
0178 {
0179     typedef pack_holder_base<typename pack_holder_builder<Ts...>::template apply<Ts, Ns>...> base;
0180     template<class X1, class X2, class... Xs>
0181     constexpr pack_base(X1&& x1, X2&& x2, Xs&&... xs)
0182     BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, X1&&, X2&&, Xs&...))
0183     : base(BOOST_HOF_FORWARD(X1)(x1), BOOST_HOF_FORWARD(X2)(x2), BOOST_HOF_FORWARD(Xs)(xs)...)
0184     {}
0185 
0186     template<class X1, typename std::enable_if<(BOOST_HOF_IS_CONSTRUCTIBLE(base, X1)), int>::type = 0>
0187     constexpr pack_base(X1&& x1)
0188     BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, X1&&))
0189     : base(BOOST_HOF_FORWARD(X1)(x1))
0190     {}
0191 
0192     // BOOST_HOF_INHERIT_DEFAULT(pack_base, typename std::remove_cv<typename std::remove_reference<Ts>::type>::type...);
0193     BOOST_HOF_INHERIT_DEFAULT(pack_base, Ts...);
0194 
0195     BOOST_HOF_RETURNS_CLASS(pack_base);
0196   
0197     template<class F>
0198     constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
0199     (
0200         f(boost::hof::detail::pack_get<Ts, pack_tag<seq<Ns>, Ts...>>(*BOOST_HOF_CONST_THIS, f)...)
0201     );
0202 
0203     typedef std::integral_constant<std::size_t, sizeof...(Ts)> fit_function_param_limit;
0204 
0205     template<class F>
0206     struct apply
0207     : F::template apply<Ts...>
0208     {};
0209 };
0210 
0211 template<class T>
0212 struct pack_base<seq<0>, T>
0213 : pack_holder_base<pack_holder<T, pack_tag<seq<0>, T>>>
0214 {
0215     typedef pack_holder_base<pack_holder<T, pack_tag<seq<0>, T>>> base;
0216 
0217     template<class X1, typename std::enable_if<(BOOST_HOF_IS_CONSTRUCTIBLE(base, X1)), int>::type = 0>
0218     constexpr pack_base(X1&& x1) 
0219     BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, X1&&))
0220     : base(BOOST_HOF_FORWARD(X1)(x1))
0221     {}
0222 
0223     BOOST_HOF_INHERIT_DEFAULT(pack_base, T);
0224 
0225     BOOST_HOF_RETURNS_CLASS(pack_base);
0226   
0227     template<class F>
0228     constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
0229     (
0230         f(boost::hof::detail::pack_get<T, pack_tag<seq<0>, T>>(*BOOST_HOF_CONST_THIS, f))
0231     );
0232 
0233     typedef std::integral_constant<std::size_t, 1> fit_function_param_limit;
0234 
0235     template<class F>
0236     struct apply
0237     : F::template apply<T>
0238     {};
0239 };
0240 
0241 #else
0242 
0243 template<std::size_t... Ns, class... Ts>
0244 struct pack_base<seq<Ns...>, Ts...>
0245 : pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type...
0246 {
0247     // BOOST_HOF_INHERIT_DEFAULT(pack_base, typename std::remove_cv<typename std::remove_reference<Ts>::type>::type...);
0248     BOOST_HOF_INHERIT_DEFAULT(pack_base, Ts...);
0249     
0250     template<class... Xs, BOOST_HOF_ENABLE_IF_CONVERTIBLE_UNPACK(Xs&&, typename pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type)>
0251     constexpr pack_base(Xs&&... xs) 
0252     BOOST_HOF_NOEXCEPT(BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(typename pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type, Xs&&)))
0253     : pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type(BOOST_HOF_FORWARD(Xs)(xs))...
0254     {}
0255 
0256     // typedef pack_base<seq<Ns...>, Ts...> self_t;
0257 
0258     BOOST_HOF_RETURNS_CLASS(pack_base);
0259   
0260     template<class F>
0261     constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
0262     (
0263         f(boost::hof::detail::pack_get<Ts, pack_tag<seq<Ns>, Ts...>>(*BOOST_HOF_CONST_THIS, f)...)
0264     );
0265 
0266     typedef std::integral_constant<std::size_t, sizeof...(Ts)> fit_function_param_limit;
0267 
0268     template<class F>
0269     struct apply
0270     : F::template apply<Ts...>
0271     {};
0272 };
0273 
0274 #endif
0275 
0276 template<>
0277 struct pack_base<seq<> >
0278 {
0279     template<class F>
0280     constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
0281     (f());
0282 
0283     typedef std::integral_constant<std::size_t, 0> fit_function_param_limit;
0284 
0285     template<class F>
0286     struct apply
0287     : F::template apply<>
0288     {};
0289 };
0290 
0291 #define BOOST_HOF_DETAIL_UNPACK_PACK_BASE(ref, move) \
0292 template<class F, std::size_t... Ns, class... Ts> \
0293 constexpr auto unpack_pack_base(F&& f, pack_base<seq<Ns...>, Ts...> ref x) \
0294 BOOST_HOF_RETURNS(f(boost::hof::alias_value<pack_tag<seq<Ns>, Ts...>, Ts>(move(x), f)...))
0295 BOOST_HOF_UNARY_PERFECT_FOREACH(BOOST_HOF_DETAIL_UNPACK_PACK_BASE)
0296 
0297 template<class P1, class P2>
0298 struct pack_join_base;
0299 
0300 // TODO: Extend to join more than two packs at a time
0301 template<std::size_t... Ns1, class... Ts1, std::size_t... Ns2, class... Ts2>
0302 struct pack_join_base<pack_base<seq<Ns1...>, Ts1...>, pack_base<seq<Ns2...>, Ts2...>>
0303 {
0304     static constexpr long total_size = sizeof...(Ts1) + sizeof...(Ts2);
0305     typedef pack_base<typename detail::gens<total_size>::type, Ts1..., Ts2...> result_type;
0306 
0307     template<class P1, class P2>
0308     static constexpr result_type call(P1&& p1, P2&& p2)
0309     BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(
0310         result_type(
0311             boost::hof::detail::pack_get<Ts1, pack_tag<seq<Ns1>, Ts1...>>(BOOST_HOF_FORWARD(P1)(p1))..., 
0312             boost::hof::detail::pack_get<Ts2, pack_tag<seq<Ns2>, Ts2...>>(BOOST_HOF_FORWARD(P2)(p2))...)
0313     )
0314     {
0315         return result_type(
0316             boost::hof::detail::pack_get<Ts1, pack_tag<seq<Ns1>, Ts1...>>(BOOST_HOF_FORWARD(P1)(p1))..., 
0317             boost::hof::detail::pack_get<Ts2, pack_tag<seq<Ns2>, Ts2...>>(BOOST_HOF_FORWARD(P2)(p2))...);
0318     }
0319 };
0320 
0321 template<class P1, class P2>
0322 struct pack_join_result 
0323 : pack_join_base<
0324     typename std::remove_cv<typename std::remove_reference<P1>::type>::type, 
0325     typename std::remove_cv<typename std::remove_reference<P2>::type>::type
0326 >
0327 {};
0328 
0329 
0330 struct pack_basic_f
0331 {
0332     template<class... Ts>
0333     constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0334     (
0335         pack_base<typename gens<sizeof...(Ts)>::type, typename remove_rvalue_reference<Ts>::type...>(BOOST_HOF_FORWARD(Ts)(xs)...)
0336     );
0337 };
0338 
0339 struct pack_forward_f
0340 {
0341     template<class... Ts>
0342     constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0343     (
0344         pack_base<typename gens<sizeof...(Ts)>::type, Ts&&...>(BOOST_HOF_FORWARD(Ts)(xs)...)
0345     );
0346 };
0347 
0348 struct pack_f
0349 {
0350     template<class... Ts>
0351     constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0352     (
0353         pack_basic_f()(boost::hof::decay(BOOST_HOF_FORWARD(Ts)(xs))...)
0354     );
0355 };
0356 
0357 template<class P1, class P2>
0358 constexpr typename pack_join_result<P1, P2>::result_type make_pack_join_dual(P1&& p1, P2&& p2)
0359 BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(pack_join_result<P1, P2>::call(BOOST_HOF_FORWARD(P1)(p1), BOOST_HOF_FORWARD(P2)(p2)))
0360 {
0361     return pack_join_result<P1, P2>::call(BOOST_HOF_FORWARD(P1)(p1), BOOST_HOF_FORWARD(P2)(p2));
0362 }
0363 
0364 // Manually compute join return type to make older gcc happy
0365 template<class... Ts>
0366 struct join_type;
0367 
0368 template<class T>
0369 struct join_type<T>
0370 {
0371     typedef T type;
0372 };
0373 
0374 template<class T, class... Ts>
0375 struct join_type<T, Ts...>
0376 {
0377     typedef typename pack_join_result<T, typename join_type<Ts...>::type>::result_type type;
0378 };
0379 
0380 template<class P1>
0381 constexpr P1 make_pack_join(P1&& p1) BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(P1, P1&&)
0382 {
0383     return BOOST_HOF_FORWARD(P1)(p1);
0384 }
0385 
0386 template<class P1, class... Ps>
0387 constexpr typename join_type<P1, Ps...>::type make_pack_join(P1&& p1, Ps&&... ps)
0388 BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(make_pack_join_dual(BOOST_HOF_FORWARD(P1)(p1), make_pack_join(BOOST_HOF_FORWARD(Ps)(ps)...)))
0389 {
0390     return make_pack_join_dual(BOOST_HOF_FORWARD(P1)(p1), make_pack_join(BOOST_HOF_FORWARD(Ps)(ps)...));
0391 }
0392 
0393 struct pack_join_f
0394 {
0395 
0396     template<class... Ps>
0397     constexpr auto operator()(Ps&&... ps) const BOOST_HOF_RETURNS
0398     (
0399         make_pack_join(BOOST_HOF_FORWARD(Ps)(ps)...)
0400     );
0401 };
0402 
0403 }
0404 
0405 BOOST_HOF_DECLARE_STATIC_VAR(pack_basic, detail::pack_basic_f);
0406 BOOST_HOF_DECLARE_STATIC_VAR(pack_forward, detail::pack_forward_f);
0407 BOOST_HOF_DECLARE_STATIC_VAR(pack, detail::pack_f);
0408 
0409 BOOST_HOF_DECLARE_STATIC_VAR(pack_join, detail::pack_join_f);
0410 
0411 template<class T, class... Ts>
0412 struct unpack_sequence<detail::pack_base<T, Ts...>>
0413 {
0414     template<class F, class P>
0415     constexpr static auto apply(F&& f, P&& p) BOOST_HOF_RETURNS
0416     (
0417         boost::hof::detail::unpack_pack_base(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(P)(p))
0418     );
0419 };
0420 
0421 }} // namespace boost::hof
0422 
0423 #endif