Edit: /usr/include/boost/hof/pack.hpp (12747B)
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
pack.h
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef BOOST_HOF_GUARD_FUNCTION_PACK_H
#define BOOST_HOF_GUARD_FUNCTION_PACK_H
/// pack
/// ====
///
/// Description
/// -----------
///
/// The `pack` function returns a higher order function object that takes a
/// function that will be passed the initial elements. The function object is
/// a sequence that can be unpacked with `unpack_adaptor` as well. Also,
/// `pack_join` can be used to join multiple packs together.
///
/// Synopsis
/// --------
///
/// // Decay everything before capturing
/// template
/// constexpr auto pack(Ts&&... xs);
///
/// // Capture lvalues by reference and rvalue reference by reference
/// template
/// constexpr auto pack_forward(Ts&&... xs);
///
/// // Capture lvalues by reference and rvalues by value.
/// template
/// constexpr auto pack_basic(Ts&&... xs);
///
/// // Join multiple packs together
/// template
/// constexpr auto pack_join(Ts&&... xs);
///
/// Semantics
/// ---------
///
/// assert(pack(xs...)(f) == f(xs...));
/// assert(unpack(f)(pack(xs...)) == f(xs...));
///
/// assert(pack_join(pack(xs...), pack(ys...)) == pack(xs..., ys...));
///
///
/// Example
/// -------
///
/// #include
/// #include
/// using namespace boost::hof;
///
/// struct sum
/// {
/// template
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// int r = pack(3, 2)(sum());
/// assert(r == 5);
/// }
///
/// See Also
/// --------
///
/// * [unpack](unpack)
///
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost { namespace hof { namespace detail {
template
struct pack_tag
{};
template
struct pack_holder
: detail::alias_empty
{};
template
struct pack_base;
template
struct is_copyable
: std::integral_constant
{};
template
struct is_copyable
: std::true_type
{};
template
struct is_copyable
: std::true_type
{};
template::value && !std::is_lvalue_reference::value
, int>::type = 0>
constexpr T pack_get(X&& x, Ts&&... xs) noexcept(BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(T))
{
return static_cast(boost::hof::alias_value(BOOST_HOF_FORWARD(X)(x), xs...));
}
template::value
, int>::type = 0>
constexpr T pack_get(X&& x, Ts&&... xs) noexcept
{
return boost::hof::alias_value(x, xs...);
}
template::value
, int>::type = 0>
constexpr auto pack_get(X&& x, Ts&&... xs) BOOST_HOF_RETURNS
(
boost::hof::alias_value(BOOST_HOF_FORWARD(X)(x), xs...)
);
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) || defined(_MSC_VER)
template
struct pack_holder_base
: Ts::type...
{
template::type>
constexpr pack_holder_base(Xs&&... xs)
BOOST_HOF_NOEXCEPT(BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(typename Ts::type, Xs&&)))
: Ts::type(BOOST_HOF_FORWARD(Xs)(xs))...
{}
#ifndef _MSC_VER
// BOOST_HOF_INHERIT_DEFAULT(pack_holder_base, typename std::remove_cv::type>::type...)
BOOST_HOF_INHERIT_DEFAULT(pack_holder_base, typename Ts::type...)
#endif
};
template
struct pack_holder_base
: T::type
{
typedef typename T::type base;
BOOST_HOF_INHERIT_CONSTRUCTOR(pack_holder_base, base);
};
template
struct pack_holder_builder
{
template
struct apply
: pack_holder, Ts...>>
{};
};
template
struct pack_base, Ts...>
: pack_holder_base::template apply...>
{
typedef pack_holder_base::template apply...> base;
template
constexpr pack_base(X1&& x1, X2&& x2, Xs&&... xs)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, X1&&, X2&&, Xs&...))
: base(BOOST_HOF_FORWARD(X1)(x1), BOOST_HOF_FORWARD(X2)(x2), BOOST_HOF_FORWARD(Xs)(xs)...)
{}
template::type = 0>
constexpr pack_base(X1&& x1)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, X1&&))
: base(BOOST_HOF_FORWARD(X1)(x1))
{}
// BOOST_HOF_INHERIT_DEFAULT(pack_base, typename std::remove_cv::type>::type...);
BOOST_HOF_INHERIT_DEFAULT(pack_base, Ts...);
BOOST_HOF_RETURNS_CLASS(pack_base);
template
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(
f(boost::hof::detail::pack_get, Ts...>>(*BOOST_HOF_CONST_THIS, f)...)
);
typedef std::integral_constant fit_function_param_limit;
template
struct apply
: F::template apply
{};
};
template
struct pack_base, T>
: pack_holder_base, T>>>
{
typedef pack_holder_base, T>>> base;
template::type = 0>
constexpr pack_base(X1&& x1)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, X1&&))
: base(BOOST_HOF_FORWARD(X1)(x1))
{}
BOOST_HOF_INHERIT_DEFAULT(pack_base, T);
BOOST_HOF_RETURNS_CLASS(pack_base);
template
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(
f(boost::hof::detail::pack_get, T>>(*BOOST_HOF_CONST_THIS, f))
);
typedef std::integral_constant fit_function_param_limit;
template
struct apply
: F::template apply
{};
};
#else
template
struct pack_base, Ts...>
: pack_holder, Ts...>>::type...
{
// BOOST_HOF_INHERIT_DEFAULT(pack_base, typename std::remove_cv::type>::type...);
BOOST_HOF_INHERIT_DEFAULT(pack_base, Ts...);
template, Ts...>>::type)>
constexpr pack_base(Xs&&... xs)
BOOST_HOF_NOEXCEPT(BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(typename pack_holder, Ts...>>::type, Xs&&)))
: pack_holder, Ts...>>::type(BOOST_HOF_FORWARD(Xs)(xs))...
{}
// typedef pack_base, Ts...> self_t;
BOOST_HOF_RETURNS_CLASS(pack_base);
template
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(
f(boost::hof::detail::pack_get, Ts...>>(*BOOST_HOF_CONST_THIS, f)...)
);
typedef std::integral_constant fit_function_param_limit;
template
struct apply
: F::template apply
{};
};
#endif
template<>
struct pack_base >
{
template
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(f());
typedef std::integral_constant fit_function_param_limit;
template
struct apply
: F::template apply<>
{};
};
#define BOOST_HOF_DETAIL_UNPACK_PACK_BASE(ref, move) \
template \
constexpr auto unpack_pack_base(F&& f, pack_base, Ts...> ref x) \
BOOST_HOF_RETURNS(f(boost::hof::alias_value, Ts...>, Ts>(move(x), f)...))
BOOST_HOF_UNARY_PERFECT_FOREACH(BOOST_HOF_DETAIL_UNPACK_PACK_BASE)
template
struct pack_join_base;
// TODO: Extend to join more than two packs at a time
template
struct pack_join_base, Ts1...>, pack_base, Ts2...>>
{
static constexpr long total_size = sizeof...(Ts1) + sizeof...(Ts2);
typedef pack_base::type, Ts1..., Ts2...> result_type;
template
static constexpr result_type call(P1&& p1, P2&& p2)
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(
result_type(
boost::hof::detail::pack_get, Ts1...>>(BOOST_HOF_FORWARD(P1)(p1))...,
boost::hof::detail::pack_get, Ts2...>>(BOOST_HOF_FORWARD(P2)(p2))...)
)
{
return result_type(
boost::hof::detail::pack_get, Ts1...>>(BOOST_HOF_FORWARD(P1)(p1))...,
boost::hof::detail::pack_get, Ts2...>>(BOOST_HOF_FORWARD(P2)(p2))...);
}
};
template
struct pack_join_result
: pack_join_base<
typename std::remove_cv::type>::type,
typename std::remove_cv::type>::type
>
{};
struct pack_basic_f
{
template
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
pack_base::type, typename remove_rvalue_reference::type...>(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
struct pack_forward_f
{
template
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
pack_base::type, Ts&&...>(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
struct pack_f
{
template
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
pack_basic_f()(boost::hof::decay(BOOST_HOF_FORWARD(Ts)(xs))...)
);
};
template
constexpr typename pack_join_result::result_type make_pack_join_dual(P1&& p1, P2&& p2)
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(pack_join_result::call(BOOST_HOF_FORWARD(P1)(p1), BOOST_HOF_FORWARD(P2)(p2)))
{
return pack_join_result::call(BOOST_HOF_FORWARD(P1)(p1), BOOST_HOF_FORWARD(P2)(p2));
}
// Manually compute join return type to make older gcc happy
template
struct join_type;
template
struct join_type
{
typedef T type;
};
template
struct join_type
{
typedef typename pack_join_result::type>::result_type type;
};
template
constexpr P1 make_pack_join(P1&& p1) BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(P1, P1&&)
{
return BOOST_HOF_FORWARD(P1)(p1);
}
template
constexpr typename join_type::type make_pack_join(P1&& p1, Ps&&... ps)
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(make_pack_join_dual(BOOST_HOF_FORWARD(P1)(p1), make_pack_join(BOOST_HOF_FORWARD(Ps)(ps)...)))
{
return make_pack_join_dual(BOOST_HOF_FORWARD(P1)(p1), make_pack_join(BOOST_HOF_FORWARD(Ps)(ps)...));
}
struct pack_join_f
{
template
constexpr auto operator()(Ps&&... ps) const BOOST_HOF_RETURNS
(
make_pack_join(BOOST_HOF_FORWARD(Ps)(ps)...)
);
};
}
BOOST_HOF_DECLARE_STATIC_VAR(pack_basic, detail::pack_basic_f);
BOOST_HOF_DECLARE_STATIC_VAR(pack_forward, detail::pack_forward_f);
BOOST_HOF_DECLARE_STATIC_VAR(pack, detail::pack_f);
BOOST_HOF_DECLARE_STATIC_VAR(pack_join, detail::pack_join_f);
template
struct unpack_sequence>
{
template
constexpr static auto apply(F&& f, P&& p) BOOST_HOF_RETURNS
(
boost::hof::detail::unpack_pack_base(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(P)(p))
);
};
}} // namespace boost::hof
#endif