File indexing completed on 2025-01-18 09:38:16
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_HOF_GUARD_FUNCTION_PACK_H
0009 #define BOOST_HOF_GUARD_FUNCTION_PACK_H
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
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
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
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
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
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
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
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 }}
0422
0423 #endif