updated boost on windows

This commit is contained in:
Bassem Girgis
2019-08-13 21:48:48 -05:00
parent 7d77d485fd
commit b40a3bee82
5162 changed files with 473027 additions and 116452 deletions

View File

@@ -0,0 +1,219 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
alias.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_ALIAS_H
#define BOOST_HOF_GUARD_ALIAS_H
#include <boost/hof/returns.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/holder.hpp>
#include <boost/hof/config.hpp>
/// alias
/// =====
///
/// Description
/// -----------
///
/// The `alias` class wraps a type with a new type that can be tagged by the
/// user. This allows defining extra attributes about the type outside of the
/// type itself. There are three different ways the value can be stored: as a
/// member variable, by inheritance, or as a static member variable. The value
/// can be retrieved uniformily using the `alias_value` function.
///
/// Synopsis
/// --------
///
/// // Alias the type using a member variable
/// template<class T, class Tag=void>
/// class alias;
///
/// // Alias the type by inheriting
/// template<class T, class Tag=void>
/// class alias_inherit;
///
/// // Alias the type using a static variable
/// template<class T, class Tag=void>
/// class alias_static;
///
/// // Retrieve tag from alias
/// template<class Alias>
/// class alias_tag;
///
/// // Check if type has a certian tag
/// template<class T, class Tag>
/// class has_tag;
///
/// // Retrieve value from alias
/// template<class Alias>
/// constexpr auto alias_value(Alias&&);
///
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4579)
#endif
namespace boost { namespace hof {
template<class T>
struct alias_tag;
template<class T, class Tag, class=void>
struct has_tag
: std::false_type
{};
template<class T, class Tag>
struct has_tag<T, Tag, typename detail::holder<
typename alias_tag<T>::type
>::type>
: std::is_same<typename alias_tag<T>::type, Tag>
{};
namespace detail {
template<class T>
constexpr T& lvalue(T& x) noexcept
{
return x;
}
template<class T>
constexpr const T& lvalue(const T& x) noexcept
{
return x;
}
}
#define BOOST_HOF_UNARY_PERFECT_FOREACH(m) \
m(const&, boost::hof::detail::lvalue) \
m(&, boost::hof::detail::lvalue) \
m(&&, boost::hof::move) \
template<class T, class Tag=void>
struct alias
{
T value;
BOOST_HOF_DELEGATE_CONSTRUCTOR(alias, T, value)
};
#define BOOST_HOF_DETAIL_ALIAS_GET_VALUE(ref, move) \
template<class Tag, class T, class... Ts> \
constexpr auto alias_value(alias<T, Tag> ref a, Ts&&...) BOOST_HOF_RETURNS(move(a.value))
BOOST_HOF_UNARY_PERFECT_FOREACH(BOOST_HOF_DETAIL_ALIAS_GET_VALUE)
template<class T, class Tag>
struct alias_tag<alias<T, Tag>>
{ typedef Tag type; };
template<class T, class Tag=void>
struct alias_inherit
#if (defined(__GNUC__) && !defined (__clang__))
: std::conditional<(std::is_class<T>::value), T, alias<T>>::type
#else
: T
#endif
{
BOOST_HOF_INHERIT_CONSTRUCTOR(alias_inherit, T)
};
#define BOOST_HOF_DETAIL_ALIAS_INHERIT_GET_VALUE(ref, move) \
template<class Tag, class T, class... Ts, class=typename std::enable_if<(BOOST_HOF_IS_CLASS(T))>::type> \
constexpr T ref alias_value(alias_inherit<T, Tag> ref a, Ts&&...) BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(move(a)) \
{ \
return move(a); \
}
BOOST_HOF_UNARY_PERFECT_FOREACH(BOOST_HOF_DETAIL_ALIAS_INHERIT_GET_VALUE)
template<class T, class Tag>
struct alias_tag<alias_inherit<T, Tag>>
{ typedef Tag type; };
namespace detail {
template<class T, class Tag>
struct alias_static_storage
{
#ifdef _MSC_VER
// Since we disable the error for 4579 on MSVC, which leaves the static
// member unitialized at runtime, it is, therefore, only safe to use this
// class on types that are empty with constructors that have no possible
// side effects.
static_assert(BOOST_HOF_IS_EMPTY(T) &&
BOOST_HOF_IS_LITERAL(T) &&
BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(T), "In-class initialization is not yet implemented on MSVC");
#endif
static constexpr T value = T();
};
template<class T, class Tag>
constexpr T alias_static_storage<T, Tag>::value;
}
template<class T, class Tag=void>
struct alias_static
{
template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
constexpr alias_static(Ts&&...) noexcept
{}
};
template<class Tag, class T, class... Ts>
constexpr const T& alias_value(const alias_static<T, Tag>&, Ts&&...) noexcept
{
return detail::alias_static_storage<T, Tag>::value;
}
template<class T, class Tag>
struct alias_tag<alias_static<T, Tag>>
{ typedef Tag type; };
namespace detail {
template<class T, class Tag>
struct alias_try_inherit
: std::conditional<(BOOST_HOF_IS_CLASS(T) && !BOOST_HOF_IS_FINAL(T) && !BOOST_HOF_IS_POLYMORPHIC(T)),
alias_inherit<T, Tag>,
alias<T, Tag>
>
{};
#if BOOST_HOF_HAS_EBO
template<class T, class Tag>
struct alias_empty
: std::conditional<(BOOST_HOF_IS_EMPTY(T)),
typename alias_try_inherit<T, Tag>::type,
alias<T, Tag>
>
{};
#else
template<class T, class Tag>
struct alias_empty
: std::conditional<
BOOST_HOF_IS_EMPTY(T) &&
BOOST_HOF_IS_LITERAL(T) &&
BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(T),
alias_static<T, Tag>,
alias<T, Tag>
>
{};
#endif
}
}} // namespace boost::hof
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,174 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
always.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_ALWAYS_H
#define BOOST_HOF_GUARD_FUNCTION_ALWAYS_H
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/unwrap.hpp>
#include <boost/hof/detail/static_const_var.hpp>
/// always
/// ======
///
/// Description
/// -----------
///
/// The `always` function returns a function object that will always return
/// the value given to it, no matter what parameters are passed to the
/// function object. The nullary version(i.e. `always(void)`) will return
/// `void`. On compilers, that don't support constexpr functions returning
/// `void`, a private empty type is returned instead. This return type is
/// specified as `BOOST_HOF_ALWAYS_VOID_RETURN`.
///
/// Synopsis
/// --------
///
/// template<class T>
/// constexpr auto always(T value);
///
/// template<class T>
/// constexpr auto always(void);
///
///
/// Semantics
/// ---------
///
/// assert(always(x)(xs...) == x);
///
/// Requirements
/// ------------
///
/// T must be:
///
/// * CopyConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <algorithm>
/// #include <cassert>
/// using namespace boost::hof;
///
/// int main() {
/// int ten = 10;
/// assert( always(ten)(1,2,3,4,5) == 10 );
/// }
///
/// // Count all
/// template<class Iterator, class T>
/// auto count(Iterator first, Iterator last)
/// {
/// return std::count_if(first, last, always(true));
/// }
///
#ifndef BOOST_HOF_NO_CONSTEXPR_VOID
#if defined(__clang__) && BOOST_HOF_HAS_RELAXED_CONSTEXPR
#define BOOST_HOF_NO_CONSTEXPR_VOID 0
#else
#define BOOST_HOF_NO_CONSTEXPR_VOID 1
#endif
#endif
namespace boost { namespace hof { namespace always_detail {
template<class T, class=void>
struct always_base
{
T x;
BOOST_HOF_DELEGATE_CONSTRUCTOR(always_base, T, x)
typedef typename detail::unwrap_reference<T>::type result_type;
template<class... As>
constexpr result_type
operator()(As&&...) const
noexcept(std::is_reference<result_type>::value || BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(result_type))
{
return this->x;
}
};
template<class T>
struct always_base<T, typename std::enable_if<!BOOST_HOF_IS_EMPTY(T)>::type>
{
T x;
constexpr always_base(T xp) noexcept(BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(T))
: x(xp)
{}
typedef typename detail::unwrap_reference<T>::type result_type;
template<class... As>
constexpr result_type
operator()(As&&...) const
noexcept(std::is_reference<result_type>::value || BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(result_type))
{
return this->x;
}
};
#if BOOST_HOF_NO_CONSTEXPR_VOID
#define BOOST_HOF_ALWAYS_VOID_RETURN boost::hof::always_detail::always_base<void>::void_
#else
#define BOOST_HOF_ALWAYS_VOID_RETURN void
#endif
template<>
struct always_base<void>
{
constexpr always_base() noexcept
{}
struct void_ {};
template<class... As>
constexpr BOOST_HOF_ALWAYS_VOID_RETURN
operator()(As&&...) const noexcept
{
#if BOOST_HOF_NO_CONSTEXPR_VOID
return void_();
#endif
}
};
struct always_f
{
template<class T>
constexpr always_detail::always_base<T> operator()(T x) const noexcept(BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(T))
{
return always_detail::always_base<T>(x);
}
constexpr always_detail::always_base<void> operator()() const noexcept
{
return always_detail::always_base<void>();
}
};
struct always_ref_f
{
template<class T>
constexpr always_detail::always_base<T&> operator()(T& x) const noexcept
{
return always_detail::always_base<T&>(x);
}
};
}
BOOST_HOF_DECLARE_STATIC_VAR(always, always_detail::always_f);
BOOST_HOF_DECLARE_STATIC_VAR(always_ref, always_detail::always_ref_f);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,252 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
apply.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_APPLY_H
#define BOOST_HOF_GUARD_APPLY_H
/// apply
/// =====
///
/// Description
/// -----------
///
/// The `apply` function calls the function given to it with its arguments.
///
/// Synopsis
/// --------
///
/// template<class F, class... Ts>
/// constexpr auto apply(F&& f, Ts&&... xs);
///
/// Semantics
/// ---------
///
/// assert(apply(f)(xs...) == f(xs...));
/// assert(fold(apply, f)(x, y, z) == f(x)(y)(z));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [Invocable](Invocable)
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct sum_f
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// assert(boost::hof::apply(sum_f(), 1, 2) == 3);
/// }
///
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4003)
#endif
#define BOOST_HOF_DETAIL_FOREACH_QUAL(m, data) \
m(, data) \
m(const, data) \
m(volatile, data) \
m(const volatile, data)
namespace boost { namespace hof {
namespace detail {
#if BOOST_HOF_HAS_MANUAL_DEDUCTION || BOOST_HOF_NO_EXPRESSION_SFINAE
struct apply_mem_fn
{
template<class...>
struct convertible_args;
template<class T, class U, class=void>
struct is_convertible_args
: std::false_type
{};
template<class... Ts, class... Us>
struct is_convertible_args<
convertible_args<Ts...>,
convertible_args<Us...>,
typename std::enable_if<(
sizeof...(Ts) == sizeof...(Us)
)>::type
>
: and_<std::is_convertible<Ts, Us>...>
{};
template<class From, class To>
struct is_compatible
: std::is_convertible<
typename std::add_pointer<typename std::remove_reference<From>::type>::type,
typename std::add_pointer<typename std::remove_reference<To>::type>::type
>
{};
#define BOOST_HOF_APPLY_MEM_FN_CALL(cv, data) \
template <class R, class Base, class Derived, class... Ts, class... Us, class=typename std::enable_if<and_< \
is_compatible<Derived, cv Base>, \
is_convertible_args<convertible_args<Us...>, convertible_args<Ts...>> \
>::value>::type> \
constexpr R operator()(R (Base::*mf)(Ts...) cv, Derived&& ref, Us &&... xs) const \
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((BOOST_HOF_FORWARD(Derived)(ref).*mf)(BOOST_HOF_FORWARD(Us)(xs)...)) \
{ \
return (BOOST_HOF_FORWARD(Derived)(ref).*mf)(BOOST_HOF_FORWARD(Us)(xs)...); \
}
BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_FN_CALL, ~)
};
struct apply_mem_data
{
template<class T, class R>
struct match_qualifier
{ typedef R type; };
#define BOOST_HOF_APPLY_MEM_DATA_MATCH(cv, ref) \
template<class T, class R> \
struct match_qualifier<cv T ref, R> \
: match_qualifier<T, cv R ref> \
{};
BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_DATA_MATCH,&)
BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_DATA_MATCH,&&)
template <class Base, class R, class Derived, class=typename std::enable_if<(
std::is_base_of<Base, typename std::decay<Derived>::type>::value
)>::type>
constexpr typename match_qualifier<Derived, R>::type
operator()(R Base::*pmd, Derived&& ref) const noexcept
{
return BOOST_HOF_FORWARD(Derived)(ref).*pmd;
}
};
template<class T, class U=decltype(*std::declval<T>())>
struct apply_deref
{ typedef U type; };
#endif
struct apply_f
{
#if BOOST_HOF_HAS_MANUAL_DEDUCTION || BOOST_HOF_NO_EXPRESSION_SFINAE
template<class F, class T, class... Ts, class=typename std::enable_if<(
std::is_member_function_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<T>, id_<Ts>...)
operator()(F&& f, T&& obj, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
apply_mem_fn()(f, BOOST_HOF_FORWARD(T)(obj), BOOST_HOF_FORWARD(Ts)(xs)...)
);
template<class F, class T, class... Ts, class U=typename apply_deref<T>::type, class=typename std::enable_if<(
std::is_member_function_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<U>, id_<Ts>...)
operator()(F&& f, T&& obj, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
apply_mem_fn()(f, *BOOST_HOF_FORWARD(T)(obj), BOOST_HOF_FORWARD(Ts)(xs)...)
);
template<class F, class T, class... Ts, class=typename std::enable_if<(
std::is_member_function_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<T&>, id_<Ts>...)
operator()(F&& f, const std::reference_wrapper<T>& ref, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
apply_mem_fn()(f, ref.get(), BOOST_HOF_FORWARD(Ts)(xs)...)
);
template<class F, class T, class=typename std::enable_if<(
std::is_member_object_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<T>)
operator()(F&& f, T&& obj) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
apply_mem_data()(f, BOOST_HOF_FORWARD(T)(obj))
);
template<class F, class T, class U=typename apply_deref<T>::type, class=typename std::enable_if<(
std::is_member_object_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<U>)
operator()(F&& f, T&& obj) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
apply_mem_data()(f, *BOOST_HOF_FORWARD(T)(obj))
);
template<class F, class T, class=typename std::enable_if<(
std::is_member_object_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<T&>)
operator()(F&& f, const std::reference_wrapper<T>& ref) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
apply_mem_data()(f, ref.get())
);
#else
template <class Base, class T, class Derived>
constexpr auto operator()(T Base::*pmd, Derived&& ref) const
BOOST_HOF_RETURNS(BOOST_HOF_FORWARD(Derived)(ref).*pmd);
template <class PMD, class Pointer>
constexpr auto operator()(PMD&& pmd, Pointer&& ptr) const
BOOST_HOF_RETURNS((*BOOST_HOF_FORWARD(Pointer)(ptr)).*BOOST_HOF_FORWARD(PMD)(pmd));
template <class Base, class T, class Derived>
constexpr auto operator()(T Base::*pmd, const std::reference_wrapper<Derived>& ref) const
BOOST_HOF_RETURNS(ref.get().*pmd);
template <class Base, class T, class Derived, class... Args>
constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const
BOOST_HOF_RETURNS((BOOST_HOF_FORWARD(Derived)(ref).*pmf)(BOOST_HOF_FORWARD(Args)(args)...));
template <class PMF, class Pointer, class... Args>
constexpr auto operator()(PMF&& pmf, Pointer&& ptr, Args&&... args) const
BOOST_HOF_RETURNS(((*BOOST_HOF_FORWARD(Pointer)(ptr)).*BOOST_HOF_FORWARD(PMF)(pmf))(BOOST_HOF_FORWARD(Args)(args)...));
template <class Base, class T, class Derived, class... Args>
constexpr auto operator()(T Base::*pmf, const std::reference_wrapper<Derived>& ref, Args&&... args) const
BOOST_HOF_RETURNS((ref.get().*pmf)(BOOST_HOF_FORWARD(Args)(args)...));
#endif
template<class F, class... Ts>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(F, id_<Ts>...)
operator()(F&& f, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
f(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
}
BOOST_HOF_DECLARE_STATIC_VAR(apply, detail::apply_f);
}} // namespace boost::hof
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,156 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
apply_eval.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_APPLY_EVAL_H
#define BOOST_HOF_GUARD_APPLY_EVAL_H
/// apply_eval
/// ==========
///
/// Description
/// -----------
///
/// The `apply_eval` function work like [`apply`](/include/boost/hof/apply), except it calls
/// [`eval`](/include/boost/hof/eval) on each of its arguments. Each [`eval`](/include/boost/hof/eval) call is
/// always ordered from left-to-right.
///
/// Synopsis
/// --------
///
/// template<class F, class... Ts>
/// constexpr auto apply_eval(F&& f, Ts&&... xs);
///
/// Semantics
/// ---------
///
/// assert(apply_eval(f)(xs...) == f(eval(xs)...));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
///
/// Ts must be:
///
/// * [EvaluatableFunctionObject](EvaluatableFunctionObject)
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct sum_f
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// assert(boost::hof::apply_eval(sum_f(), []{ return 1; }, []{ return 2; }) == 3);
/// }
///
#include <boost/hof/config.hpp>
#include <boost/hof/returns.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/apply.hpp>
#include <boost/hof/eval.hpp>
#if BOOST_HOF_NO_ORDERED_BRACE_INIT
#include <boost/hof/pack.hpp>
#include <boost/hof/capture.hpp>
#endif
namespace boost { namespace hof {
namespace detail {
#if BOOST_HOF_NO_ORDERED_BRACE_INIT
template<class R, class F, class Pack>
constexpr R eval_ordered(const F& f, Pack&& p)
{
return p(f);
}
template<class R, class F, class Pack, class T, class... Ts>
constexpr R eval_ordered(const F& f, Pack&& p, T&& x, Ts&&... xs)
{
return boost::hof::detail::eval_ordered<R>(f, boost::hof::pack_join(BOOST_HOF_FORWARD(Pack)(p), boost::hof::pack_forward(boost::hof::eval(x))), BOOST_HOF_FORWARD(Ts)(xs)...);
}
#else
template<class R>
struct eval_helper
{
R result;
template<class F, class... Ts>
constexpr eval_helper(const F& f, Ts&&... xs) : result(boost::hof::apply(f, BOOST_HOF_FORWARD(Ts)(xs)...))
{}
};
template<>
struct eval_helper<void>
{
int x;
template<class F, class... Ts>
constexpr eval_helper(const F& f, Ts&&... xs) : x((boost::hof::apply(f, BOOST_HOF_FORWARD(Ts)(xs)...), 0))
{}
};
#endif
struct apply_eval_f
{
template<class F, class... Ts, class R=decltype(
boost::hof::apply(std::declval<const F&>(), boost::hof::eval(std::declval<Ts>())...)
),
class=typename std::enable_if<(!std::is_void<R>::value)>::type
>
constexpr R operator()(const F& f, Ts&&... xs) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(boost::hof::apply(f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...))
{
return
#if BOOST_HOF_NO_ORDERED_BRACE_INIT
boost::hof::detail::eval_ordered<R>
(f, boost::hof::pack(), BOOST_HOF_FORWARD(Ts)(xs)...);
#else
boost::hof::detail::eval_helper<R>
{f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...}.result;
#endif
}
template<class F, class... Ts, class R=decltype(
boost::hof::apply(std::declval<const F&>(), boost::hof::eval(std::declval<Ts>())...)
),
class=typename std::enable_if<(std::is_void<R>::value)>::type
>
constexpr typename detail::holder<Ts...>::type
operator()(const F& f, Ts&&... xs) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(boost::hof::apply(f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...))
{
return (typename detail::holder<Ts...>::type)
#if BOOST_HOF_NO_ORDERED_BRACE_INIT
boost::hof::detail::eval_ordered<R>
(f, boost::hof::pack(), BOOST_HOF_FORWARD(Ts)(xs)...);
#else
boost::hof::detail::eval_helper<R>
{f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...};
#endif
}
};
}
BOOST_HOF_DECLARE_STATIC_VAR(apply_eval, detail::apply_eval_f);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,126 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
arg.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_ARGS_H
#define BOOST_HOF_GUARD_FUNCTION_ARGS_H
#include <boost/hof/detail/seq.hpp>
#include <boost/hof/returns.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <utility>
/// arg
/// ===
///
/// Description
/// -----------
///
/// The `arg` function returns a function object that returns the Nth argument
/// passed to it. It actually starts at 1, so it is not the zero-based index
/// of the argument.
///
/// Synopsis
/// --------
///
/// template<class IntegralConstant>
/// constexpr auto arg(IntegralConstant);
///
/// template<std::size_t N, class... Ts>
/// constexpr auto arg_c(Ts&&...);
///
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// int main() {
/// assert(arg(std::integral_constant<int, 3>())(1,2,3,4,5) == 3);
/// }
///
namespace boost { namespace hof {
namespace detail {
template<class T>
struct perfect_ref
{
typedef T type;
typedef typename std::remove_reference<T>::type value_type;
T&& value;
constexpr perfect_ref(value_type& x) noexcept
: value(BOOST_HOF_FORWARD(T)(x))
{}
};
template<std::size_t N>
struct ignore
{
template<class T>
constexpr ignore(T&&...) noexcept
{}
};
template<std::size_t... N>
struct args_at
{
template<class T, class... Ts>
constexpr auto operator()(ignore<N>..., T x, Ts...) const
BOOST_HOF_RETURNS(BOOST_HOF_FORWARD(typename T::type)(x.value));
};
template<std::size_t... N>
constexpr args_at<N...> make_args_at(seq<N...>) noexcept
{
return {};
}
template<std::size_t N, class... Ts>
constexpr auto get_args(Ts&&... xs) BOOST_HOF_RETURNS
(
boost::hof::detail::make_args_at(typename gens<N>::type())(nullptr, BOOST_HOF_RETURNS_CONSTRUCT(perfect_ref<Ts>)(xs)...)
);
template<class T, T N>
struct make_args_f
{
template<class... Ts, class=typename std::enable_if<(N <= sizeof...(Ts))>::type>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
boost::hof::detail::get_args<N>(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
struct arg_f
{
template<class IntegralConstant>
constexpr make_args_f<std::size_t, IntegralConstant::value> operator()(IntegralConstant) const noexcept
{
return make_args_f<std::size_t, IntegralConstant::value>();
}
};
}
#if BOOST_HOF_HAS_VARIABLE_TEMPLATES
template<std::size_t N>
BOOST_HOF_STATIC_CONSTEXPR detail::make_args_f<std::size_t, N> arg_c = {};
#else
template<std::size_t N, class... Ts>
constexpr auto arg_c(Ts&&... xs) BOOST_HOF_RETURNS
(
boost::hof::detail::get_args<N>(BOOST_HOF_FORWARD(Ts)(xs)...)
);
#endif
BOOST_HOF_DECLARE_STATIC_VAR(arg, detail::arg_f);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,189 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
capture.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_CAPTURE_H
#define BOOST_HOF_GUARD_CAPTURE_H
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/pack.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/result_type.hpp>
/// capture
/// =======
///
/// Description
/// -----------
///
/// The `capture` function decorator is used to capture values in a function.
/// It provides more flexibility in capturing than the lambda capture list in
/// C++. It provides a way to do move and perfect capturing. The values
/// captured are prepended to the argument list of the function that will be
/// called.
///
/// Synopsis
/// --------
///
/// // Capture by decaying each value
/// template<class... Ts>
/// constexpr auto capture(Ts&&... xs);
///
/// // Capture lvalues by reference and rvalue reference by reference
/// template<class... Ts>
/// constexpr auto capture_forward(Ts&&... xs);
///
/// // Capture lvalues by reference and rvalues by value.
/// template<class... Ts>
/// constexpr auto capture_basic(Ts&&... xs);
///
/// Semantics
/// ---------
///
/// assert(capture(xs...)(f)(ys...) == f(xs..., ys...));
///
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct sum_f
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// auto add_one = boost::hof::capture(1)(sum_f());
/// assert(add_one(2) == 3);
/// }
///
namespace boost { namespace hof {
namespace detail {
template<class F, class Pack>
struct capture_invoke : detail::compressed_pair<detail::callable_base<F>, Pack>, detail::function_result_type<F>
{
typedef capture_invoke fit_rewritable1_tag;
typedef detail::compressed_pair<detail::callable_base<F>, Pack> base;
BOOST_HOF_INHERIT_CONSTRUCTOR(capture_invoke, base)
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return this->first(xs...);
}
template<class... Ts>
constexpr const Pack& get_pack(Ts&&...xs) const noexcept
{
return this->second(xs...);
}
template<class Failure, class... Ts>
struct unpack_capture_failure
{
template<class... Us>
struct apply
{
typedef typename Failure::template of<Us..., Ts...> type;
};
};
struct capture_failure
{
template<class Failure>
struct apply
{
template<class... Ts>
struct of
: Pack::template apply<unpack_capture_failure<Failure, Ts...>>::type
{};
};
};
struct failure
: failure_map<capture_failure, detail::callable_base<F>>
{};
BOOST_HOF_RETURNS_CLASS(capture_invoke);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT
(
typename result_of<decltype(boost::hof::pack_join),
id_<const Pack&>,
result_of<decltype(boost::hof::pack_forward), id_<Ts>...>
>::type,
id_<detail::callable_base<F>&&>
)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
boost::hof::pack_join
(
BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(xs...)),
boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)
)
(BOOST_HOF_RETURNS_C_CAST(detail::callable_base<F>&&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
);
};
template<class Pack>
struct capture_pack : Pack
{
BOOST_HOF_INHERIT_CONSTRUCTOR(capture_pack, Pack);
BOOST_HOF_RETURNS_CLASS(capture_pack);
// TODO: Should use rvalue ref qualifier
template<class F>
constexpr auto operator()(F f) const BOOST_HOF_SFINAE_RETURNS
(
capture_invoke<F, Pack>(BOOST_HOF_RETURNS_STATIC_CAST(F&&)(f),
BOOST_HOF_RETURNS_C_CAST(Pack&&)(
BOOST_HOF_RETURNS_STATIC_CAST(const Pack&)(*boost::hof::always(BOOST_HOF_CONST_THIS)(f))
)
)
);
};
struct make_capture_pack_f
{
template<class Pack>
constexpr capture_pack<Pack> operator()(Pack p) const
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(capture_pack<Pack>, Pack&&)
{
return capture_pack<Pack>(static_cast<Pack&&>(p));
}
};
template<class F>
struct capture_f
{
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
BOOST_HOF_RETURNS_CONSTRUCT(make_capture_pack_f)()(BOOST_HOF_RETURNS_CONSTRUCT(F)()(BOOST_HOF_FORWARD(Ts)(xs)...))
);
};
}
BOOST_HOF_DECLARE_STATIC_VAR(capture_basic, detail::capture_f<detail::pack_basic_f>);
BOOST_HOF_DECLARE_STATIC_VAR(capture_forward, detail::capture_f<detail::pack_forward_f>);
BOOST_HOF_DECLARE_STATIC_VAR(capture, detail::capture_f<detail::pack_f>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,126 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
combine.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_COMBINE_H
#define BOOST_HOF_GUARD_COMBINE_H
/// combine
/// =======
///
/// Description
/// -----------
///
/// The `combine` function adaptor combines several functions together with
/// their arguments. It essentially zips each function with an argument before
/// calling the main function.
///
/// Synopsis
/// --------
///
/// template<class F, class... Gs>
/// constexpr combine_adaptor<F, Gs...> combine(F f, Gs... gs);
///
/// Semantics
/// ---------
///
/// assert(combine(f, gs...)(xs...) == f(gs(xs)...));
///
/// Requirements
/// ------------
///
/// F and Gs must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// #include <tuple>
/// #include <utility>
///
/// int main() {
/// auto f = boost::hof::combine(
/// boost::hof::construct<std::tuple>(),
/// boost::hof::capture(1)(boost::hof::construct<std::pair>()),
/// boost::hof::capture(2)(boost::hof::construct<std::pair>()));
/// assert(f(3, 7) == std::make_tuple(std::make_pair(1, 3), std::make_pair(2, 7)));
/// }
///
#include <boost/hof/pack.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/make.hpp>
namespace boost { namespace hof { namespace detail {
template<class S, class F, class... Gs>
struct combine_adaptor_base;
template<std::size_t... Ns, class F, class... Gs>
struct combine_adaptor_base<seq<Ns...>, F, Gs...>
: F, pack_base<seq<Ns...>, Gs...>
{
typedef pack_base<seq<Ns...>, Gs...> base_type;
BOOST_HOF_INHERIT_DEFAULT(combine_adaptor_base, base_type, F)
template<class X, class... Xs,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(F, X),
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(base_type, Xs...)>
constexpr combine_adaptor_base(X&& x, Xs&&... xs)
: F(BOOST_HOF_FORWARD(X)(x)), base_type(BOOST_HOF_FORWARD(Xs)(xs)...)
{}
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(combine_adaptor_base);
// Result needs to be calculated in a separate class to avoid confusing the
// compiler on MSVC
#if BOOST_HOF_NO_EXPRESSION_SFINAE || BOOST_HOF_HAS_MANUAL_DEDUCTION
template<class... Ts>
struct combine_result
: result_of<const F&, result_of<const Gs&, id_<Ts>>...>
{};
#endif
template<class... Ts>
#if BOOST_HOF_NO_EXPRESSION_SFINAE || BOOST_HOF_HAS_MANUAL_DEDUCTION
constexpr typename combine_result<Ts...>::type
#else
constexpr auto
#endif
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
(BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
(boost::hof::alias_value<pack_tag<seq<Ns>, Gs...>, Gs>(*BOOST_HOF_CONST_THIS, xs)(BOOST_HOF_FORWARD(Ts)(xs))...)
);
};
}
template<class F, class... Gs>
struct combine_adaptor
: detail::combine_adaptor_base<typename detail::gens<sizeof...(Gs)>::type, detail::callable_base<F>, detail::callable_base<Gs>...>
{
typedef detail::combine_adaptor_base<typename detail::gens<sizeof...(Gs)>::type, detail::callable_base<F>, detail::callable_base<Gs>...> base_type;
BOOST_HOF_INHERIT_CONSTRUCTOR(combine_adaptor, base_type)
};
BOOST_HOF_DECLARE_STATIC_VAR(combine, detail::make<combine_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,169 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
compose.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_COMPOSE_H
#define BOOST_HOF_GUARD_FUNCTION_COMPOSE_H
/// compose
/// =======
///
/// Description
/// -----------
///
/// The `compose` function adaptor provides function composition. It produces
/// a function object that composes a set of functions, ie the output of one
/// function becomes the input of the second function. So, `compose(f, g)(0)`
/// is equivalent to `f(g(0))`.
///
///
/// Synopsis
/// --------
///
/// template<class... Fs>
/// constexpr compose_adaptor<Fs...> compose(Fs... fs);
///
/// Semantics
/// ---------
///
/// assert(compose(f, g)(xs...) == f(g(xs...)));
///
/// Requirements
/// ------------
///
/// Fs must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct increment
/// {
/// template<class T>
/// T operator()(T x) const
/// {
/// return x + 1;
/// }
/// };
///
/// struct decrement
/// {
/// template<class T>
/// T operator()(T x) const
/// {
/// return x - 1;
/// }
/// };
///
/// int main() {
/// int r = compose(increment(), decrement(), increment())(3);
/// assert(r == 4);
/// }
///
/// References
/// ----------
///
/// * [Function composition](https://en.wikipedia.org/wiki/Function_composition)
///
///
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/detail/join.hpp>
#include <tuple>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/result_type.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof { namespace detail {
template<class F1, class F2>
struct compose_kernel : detail::compressed_pair<F1, F2>, compose_function_result_type<F1, F2>
{
typedef detail::compressed_pair<F1, F2> base_type;
BOOST_HOF_INHERIT_CONSTRUCTOR(compose_kernel, base_type)
BOOST_HOF_RETURNS_CLASS(compose_kernel);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const F1&, result_of<const F2&, id_<Ts>...>)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
BOOST_HOF_MANGLE_CAST(const F1&)(BOOST_HOF_CONST_THIS->first(xs...))(
BOOST_HOF_MANGLE_CAST(const F2&)(BOOST_HOF_CONST_THIS->second(xs...))(BOOST_HOF_FORWARD(Ts)(xs)...)
)
);
};
}
template<class F, class... Fs>
struct compose_adaptor
: detail::compose_kernel<detail::callable_base<F>, BOOST_HOF_JOIN(compose_adaptor, detail::callable_base<Fs>...)>
{
typedef compose_adaptor fit_rewritable_tag;
typedef BOOST_HOF_JOIN(compose_adaptor, detail::callable_base<Fs>...) tail;
typedef detail::compose_kernel<detail::callable_base<F>, tail> base_type;
BOOST_HOF_INHERIT_DEFAULT(compose_adaptor, base_type)
template<class X, class... Xs,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(detail::callable_base<F>, X),
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(tail, Xs...)
>
constexpr compose_adaptor(X&& f1, Xs&& ... fs)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base_type, X&&, tail) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(tail, Xs&&...))
: base_type(BOOST_HOF_FORWARD(X)(f1), tail(BOOST_HOF_FORWARD(Xs)(fs)...))
{}
template<class X,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(detail::callable_base<F>, X)
>
constexpr compose_adaptor(X&& f1)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(base_type, X&&)
: base_type(BOOST_HOF_FORWARD(X)(f1))
{}
};
template<class F>
struct compose_adaptor<F> : detail::callable_base<F>
{
typedef compose_adaptor fit_rewritable_tag;
BOOST_HOF_INHERIT_DEFAULT(compose_adaptor, detail::callable_base<F>)
template<class X, BOOST_HOF_ENABLE_IF_CONVERTIBLE(X, detail::callable_base<F>)>
constexpr compose_adaptor(X&& f1)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(detail::callable_base<F>, X&&)
: detail::callable_base<F>(BOOST_HOF_FORWARD(X)(f1))
{}
};
template<class F1, class F2>
struct compose_adaptor<F1, F2>
: detail::compose_kernel<detail::callable_base<F1>, detail::callable_base<F2>>
{
typedef compose_adaptor fit_rewritable_tag;
typedef detail::compose_kernel<detail::callable_base<F1>, detail::callable_base<F2>> base_type;
BOOST_HOF_INHERIT_CONSTRUCTOR(compose_adaptor, base_type)
};
BOOST_HOF_DECLARE_STATIC_VAR(compose, detail::make<compose_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,201 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
config.hpp
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_CONFIG_HPP
#define BOOST_HOF_GUARD_CONFIG_HPP
// Unpack has extra checks to ensure that the function will be invoked with
// the sequence. This extra check can help improve error reporting but it can
// slow down compilation. This is enabled by default.
#ifndef BOOST_HOF_CHECK_UNPACK_SEQUENCE
#define BOOST_HOF_CHECK_UNPACK_SEQUENCE 1
#endif
// Check for std version
#if __cplusplus >= 201606
#define BOOST_HOF_HAS_STD_17 1
#else
#define BOOST_HOF_HAS_STD_17 0
#endif
#if __cplusplus >= 201402
#define BOOST_HOF_HAS_STD_14 1
#else
#define BOOST_HOF_HAS_STD_14 0
#endif
#if __cplusplus >= 201103
#define BOOST_HOF_HAS_STD_11 1
#else
#define BOOST_HOF_HAS_STD_11 0
#endif
// This determines if it safe to use inheritance for EBO. On every platform
// except clang, compilers have problems with ambigous base conversion. So
// this configures the library to use a different technique to achieve empty
// optimization.
#ifndef BOOST_HOF_HAS_EBO
#ifdef __clang__
#define BOOST_HOF_HAS_EBO 1
#else
#define BOOST_HOF_HAS_EBO 0
#endif
#endif
// This configures the library whether expression sfinae can be used to detect
// callability of a function.
#ifndef BOOST_HOF_NO_EXPRESSION_SFINAE
#ifdef _MSC_VER
#define BOOST_HOF_NO_EXPRESSION_SFINAE 1
#else
#define BOOST_HOF_NO_EXPRESSION_SFINAE 0
#endif
#endif
// This configures the library to use manual type deduction in a few places
// where it problematic on a few platforms.
#ifndef BOOST_HOF_HAS_MANUAL_DEDUCTION
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 8)
#define BOOST_HOF_HAS_MANUAL_DEDUCTION 1
#else
#define BOOST_HOF_HAS_MANUAL_DEDUCTION 0
#endif
#endif
// Whether the compiler has relaxed constexpr.
#ifndef BOOST_HOF_HAS_RELAXED_CONSTEXPR
#ifdef __cpp_constexpr
#if __cpp_constexpr >= 201304
#define BOOST_HOF_HAS_RELAXED_CONSTEXPR 1
#else
#define BOOST_HOF_HAS_RELAXED_CONSTEXPR 0
#endif
#else
#define BOOST_HOF_HAS_RELAXED_CONSTEXPR BOOST_HOF_HAS_STD_14
#endif
#endif
// Whether the compiler supports generic lambdas
#ifndef BOOST_HOF_HAS_GENERIC_LAMBDA
#if defined(__cpp_generic_lambdas) || defined(_MSC_VER)
#define BOOST_HOF_HAS_GENERIC_LAMBDA 1
#else
#define BOOST_HOF_HAS_GENERIC_LAMBDA BOOST_HOF_HAS_STD_14
#endif
#endif
// Whether the compiler supports constexpr lambdas
#ifndef BOOST_HOF_HAS_CONSTEXPR_LAMBDA
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201603
#define BOOST_HOF_HAS_CONSTEXPR_LAMBDA 1
#else
#define BOOST_HOF_HAS_CONSTEXPR_LAMBDA BOOST_HOF_HAS_STD_17
#endif
#endif
// Whether the compiler supports inline variables
#ifndef BOOST_HOF_HAS_INLINE_VARIABLES
#if defined(__cpp_inline_variables)
#define BOOST_HOF_HAS_INLINE_VARIABLES 1
#else
#define BOOST_HOF_HAS_INLINE_VARIABLES BOOST_HOF_HAS_STD_17
#endif
#endif
// Whether inline variables defined with lambdas have external linkage.
// Currently, no compiler supports this yet.
#ifndef BOOST_HOF_HAS_INLINE_LAMBDAS
#define BOOST_HOF_HAS_INLINE_LAMBDAS 0
#endif
// Whether the compiler supports variable templates
#ifndef BOOST_HOF_HAS_VARIABLE_TEMPLATES
#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ < 5
#define BOOST_HOF_HAS_VARIABLE_TEMPLATES 0
#elif defined(__cpp_variable_templates)
#define BOOST_HOF_HAS_VARIABLE_TEMPLATES 1
#else
#define BOOST_HOF_HAS_VARIABLE_TEMPLATES BOOST_HOF_HAS_STD_14
#endif
#endif
// Whether a constexpr function can use a void return type
#ifndef BOOST_HOF_NO_CONSTEXPR_VOID
#if BOOST_HOF_HAS_RELAXED_CONSTEXPR
#define BOOST_HOF_NO_CONSTEXPR_VOID 0
#else
#define BOOST_HOF_NO_CONSTEXPR_VOID 1
#endif
#endif
// Whether to use template aliases
#ifndef BOOST_HOF_HAS_TEMPLATE_ALIAS
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 8
#define BOOST_HOF_HAS_TEMPLATE_ALIAS 0
#else
#define BOOST_HOF_HAS_TEMPLATE_ALIAS 1
#endif
#endif
// Whether evaluations of function in brace initialization is ordered from
// left-to-right.
#ifndef BOOST_HOF_NO_ORDERED_BRACE_INIT
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9) || defined(_MSC_VER)
#define BOOST_HOF_NO_ORDERED_BRACE_INIT 1
#else
#define BOOST_HOF_NO_ORDERED_BRACE_INIT 0
#endif
#endif
// Whether the compiler has trouble mangling some expressions used in
// decltype.
#ifndef BOOST_HOF_HAS_MANGLE_OVERLOAD
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_HAS_MANGLE_OVERLOAD 0
#else
#define BOOST_HOF_HAS_MANGLE_OVERLOAD 1
#endif
#endif
// Whether an incomplete 'this' pointer can be used in a trailing decltype.
#ifndef BOOST_HOF_HAS_COMPLETE_DECLTYPE
#if !BOOST_HOF_HAS_MANGLE_OVERLOAD || (defined(__GNUC__) && !defined (__clang__))
#define BOOST_HOF_HAS_COMPLETE_DECLTYPE 0
#else
#define BOOST_HOF_HAS_COMPLETE_DECLTYPE 1
#endif
#endif
// Whether function will deduce noexcept from an expression
#ifndef BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
#if defined(__GNUC__) && !defined (__clang__) && ((__GNUC__ == 4 && __GNUC_MINOR__ < 8) || (__GNUC__ == 7 && __GNUC_MINOR__ == 1))
#define BOOST_HOF_HAS_NOEXCEPT_DEDUCTION 0
#else
#define BOOST_HOF_HAS_NOEXCEPT_DEDUCTION 1
#endif
#endif
// Some type expansion failures on gcc 4.6
#ifndef BOOST_HOF_NO_TYPE_PACK_EXPANSION_IN_TEMPLATE
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_NO_TYPE_PACK_EXPANSION_IN_TEMPLATE 1
#else
#define BOOST_HOF_NO_TYPE_PACK_EXPANSION_IN_TEMPLATE 0
#endif
#endif
// Whether to use std::default_constructible, it is a little buggy on gcc 4.6.
#ifndef BOOST_HOF_NO_STD_DEFAULT_CONSTRUCTIBLE
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_NO_STD_DEFAULT_CONSTRUCTIBLE 1
#else
#define BOOST_HOF_NO_STD_DEFAULT_CONSTRUCTIBLE 0
#endif
#endif
#endif

View File

@@ -0,0 +1,302 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
construct.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_CONSTRUCT_H
#define BOOST_HOF_GUARD_CONSTRUCT_H
/// construct
/// =========
///
/// Description
/// -----------
///
/// The `construct` function returns a function object that will construct the
/// object when the called. A template can also be given, which it will deduce
/// the parameters to the template. The `construct_meta` can be used to
/// construct the object from a metafunction.
///
/// Synopsis
/// --------
///
/// // Construct by decaying each value
/// template<class T>
/// constexpr auto construct();
///
/// template<template<class...> class Template>
/// constexpr auto construct();
///
/// // Construct by deducing lvalues by reference and rvalue reference by reference
/// template<class T>
/// constexpr auto construct_forward();
///
/// template<template<class...> class Template>
/// constexpr auto construct_forward();
///
/// // Construct by deducing lvalues by reference and rvalues by value.
/// template<class T>
/// constexpr auto construct_basic();
///
/// template<template<class...> class Template>
/// constexpr auto construct_basic();
///
/// // Construct by deducing the object from a metafunction
/// template<class MetafunctionClass>
/// constexpr auto construct_meta();
///
/// template<template<class...> class MetafunctionTemplate>
/// constexpr auto construct_meta();
///
/// Semantics
/// ---------
///
/// assert(construct<T>()(xs...) == T(xs...));
/// assert(construct<Template>()(xs...) == Template<decltype(xs)...>(xs...));
/// assert(construct_meta<MetafunctionClass>()(xs...) == MetafunctionClass::apply<decltype(xs)...>(xs...));
/// assert(construct_meta<MetafunctionTemplate>()(xs...) == MetafunctionTemplate<decltype(xs)...>::type(xs...));
///
/// Requirements
/// ------------
///
/// MetafunctionClass must be a:
///
/// * [MetafunctionClass](MetafunctionClass)
///
/// MetafunctionTemplate<Ts...> must be a:
///
/// * [Metafunction](Metafunction)
///
/// T, Template<Ts..>, MetafunctionClass::apply<Ts...>, and
/// MetafunctionTemplate<Ts...>::type must be:
///
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// #include <vector>
///
/// int main() {
/// auto v = boost::hof::construct<std::vector<int>>()(5, 5);
/// assert(v.size() == 5);
/// }
///
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/join.hpp>
#include <boost/hof/detail/remove_rvalue_reference.hpp>
#include <boost/hof/decay.hpp>
#include <initializer_list>
namespace boost { namespace hof {
namespace detail {
template<class T, class=void>
struct construct_f
{
typedef typename std::aligned_storage<sizeof(T)>::type storage;
struct storage_holder
{
storage * s;
storage_holder(storage* x) noexcept : s(x)
{}
T& data() noexcept
{
return *reinterpret_cast<T*>(s);
}
~storage_holder() noexcept(noexcept(std::declval<T>().~T()))
{
this->data().~T();
}
};
constexpr construct_f() noexcept
{}
template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
T operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, Ts&&...)
{
storage buffer{};
new(&buffer) T(BOOST_HOF_FORWARD(Ts)(xs)...);
storage_holder h(&buffer);
return boost::hof::move(h.data());
}
template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)>
T operator()(std::initializer_list<X>&& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&&)
{
storage buffer{};
new(&buffer) T(static_cast<std::initializer_list<X>&&>(x));
storage_holder h(&buffer);
return h.data();
}
template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)>
T operator()(std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&)
{
storage buffer{};
new(&buffer) T(x);
storage_holder h(&buffer);
return h.data();
}
template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)>
T operator()(const std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, const std::initializer_list<X>&)
{
storage buffer{};
new(&buffer) T(x);
storage_holder h(&buffer);
return h.data();
}
};
template<class T>
struct construct_f<T, typename std::enable_if<BOOST_HOF_IS_LITERAL(T)>::type>
{
constexpr construct_f() noexcept
{}
template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
constexpr T operator()(Ts&&... xs) const noexcept
{
return T(BOOST_HOF_FORWARD(Ts)(xs)...);
}
template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)>
constexpr T operator()(std::initializer_list<X>&& x) const noexcept
{
return T(static_cast<std::initializer_list<X>&&>(x));
}
template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)>
constexpr T operator()(std::initializer_list<X>& x) const noexcept
{
return T(x);
}
template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)>
constexpr T operator()(const std::initializer_list<X>& x) const noexcept
{
return T(x);
}
};
template<template<class...> class Template, template<class...> class D>
struct construct_template_f
{
constexpr construct_template_f() noexcept
{}
template<class... Ts, class Result=BOOST_HOF_JOIN(Template, typename D<Ts>::type...),
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
{
return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
}
};
template<class MetafunctionClass>
struct construct_meta_f
{
constexpr construct_meta_f() noexcept
{}
template<class... Ts>
struct apply
: MetafunctionClass::template apply<Ts...>
{};
template<class... Ts,
class Metafunction=BOOST_HOF_JOIN(apply, Ts...),
class Result=typename Metafunction::type,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
{
return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
}
};
template<template<class...> class MetafunctionTemplate>
struct construct_meta_template_f
{
constexpr construct_meta_template_f() noexcept
{}
template<class... Ts,
class Metafunction=BOOST_HOF_JOIN(MetafunctionTemplate, Ts...),
class Result=typename Metafunction::type,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
{
return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
}
};
template<class T>
struct construct_id
{
typedef T type;
};
}
template<class T>
constexpr detail::construct_f<T> construct() noexcept
{
return {};
}
// These overloads are provide for consistency
template<class T>
constexpr detail::construct_f<T> construct_forward() noexcept
{
return {};
}
template<class T>
constexpr detail::construct_f<T> construct_basic() noexcept
{
return {};
}
template<template<class...> class Template>
constexpr detail::construct_template_f<Template, detail::decay_mf> construct() noexcept
{
return {};
}
template<template<class...> class Template>
constexpr detail::construct_template_f<Template, detail::construct_id> construct_forward() noexcept
{
return {};
}
template<template<class...> class Template>
constexpr detail::construct_template_f<Template, detail::remove_rvalue_reference> construct_basic() noexcept
{
return {};
}
template<class T>
constexpr detail::construct_meta_f<T> construct_meta() noexcept
{
return {};
}
template<template<class...> class Template>
constexpr detail::construct_meta_template_f<Template> construct_meta() noexcept
{
return {};
}
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,68 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
decay.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_DECAY_H
#define BOOST_HOF_GUARD_DECAY_H
/// decay
/// =====
///
/// Description
/// -----------
///
/// The `decay` function is a unary function object that returns whats given to it after decaying its type.
///
/// Synopsis
/// --------
///
/// struct
/// {
/// template<class T>
/// constexpr typename decay<T>::type operator()(T&& x) const
/// {
/// return boost::hof::forward<T>(x);
/// }
/// } decay;
///
/// References
/// ----------
///
/// * [n3255](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3255.html) - Proposal for `decay_copy`
///
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/unwrap.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/detail/forward.hpp>
namespace boost { namespace hof { namespace detail {
template<class T>
struct decay_mf
: unwrap_reference<typename std::decay<T>::type>
{};
struct decay_f
{
template<
class T,
class Result=typename unwrap_reference<typename std::decay<T>::type>::type,
class=typename std::enable_if<(BOOST_HOF_IS_CONSTRUCTIBLE(Result, T))>::type
>
constexpr Result operator()(T&& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, T&&)
{
return BOOST_HOF_FORWARD(T)(x);
}
};
}
BOOST_HOF_DECLARE_STATIC_VAR(decay, detail::decay_f);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,217 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
decorate.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_DECORATE_H
#define BOOST_HOF_GUARD_DECORATE_H
/// decorate
/// ========
///
/// Description
/// -----------
///
/// The `decorate` function adaptor helps create simple function decorators.
///
/// A function adaptor takes a function and returns a new functions whereas a
/// decorator takes some parameters and returns a function adaptor. The
/// `decorate` function adaptor will return a decorator that returns a
/// function adaptor. Eventually, it will invoke the function with the user-
/// provided parameter and function.
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr decorate_adaptor<F> decorate(F f);
///
/// Semantics
/// ---------
///
/// assert(decorate(f)(x)(g)(xs...) == f(x, g, xs...));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// #include <iostream>
/// #include <string>
/// using namespace boost::hof;
///
/// struct logger_f
/// {
/// template<class F, class... Ts>
/// auto operator()(const std::string& message, F&& f, Ts&&... xs) const
/// -> decltype(f(std::forward<Ts>(xs)...))
/// {
/// // Message to print out when the function is called
/// std::cout << message << std::endl;
/// // Call the function
/// return f(std::forward<Ts>(xs)...);
/// }
/// };
/// // The logger decorator
/// BOOST_HOF_STATIC_FUNCTION(logger) = boost::hof::decorate(logger_f());
///
/// struct sum_f
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// BOOST_HOF_STATIC_FUNCTION(sum) = sum_f();
/// int main() {
/// // Use the logger decorator to print "Calling sum" when the function is called
/// assert(3 == logger("Calling sum")(sum)(1, 2));
/// }
///
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
namespace boost { namespace hof { namespace detail {
template<class D, class T, class F>
struct decorator_invoke
// : compressed_pair<compressed_pair<F, T>, D>
: compressed_pair<compressed_pair<D, T>, F>
{
// typedef compressed_pair<F, T> base;
typedef compressed_pair<compressed_pair<D, T>, F> base;
BOOST_HOF_INHERIT_CONSTRUCTOR(decorator_invoke, base)
template<class... Ts>
constexpr const compressed_pair<D, T>& get_pair(Ts&&... xs) const noexcept
{
return this->first(xs...);
}
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const noexcept
{
return this->second(xs...);
}
template<class... Ts>
constexpr const D& get_decorator(Ts&&... xs) const noexcept
{
return this->get_pair(xs...).first(xs...);
}
template<class... Ts>
constexpr const T& get_data(Ts&&... xs) const noexcept
{
return this->get_pair(xs...).second(xs...);
}
BOOST_HOF_RETURNS_CLASS(decorator_invoke);
struct decorator_invoke_failure
{
template<class Failure>
struct apply
{
template<class... Ts>
struct of
: Failure::template of<const T&, const F&, Ts...>
{};
};
};
struct failure
: failure_map<decorator_invoke_failure, D>
{};
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const D&, id_<const T&>, id_<const F&>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
BOOST_HOF_MANGLE_CAST(const D&)(BOOST_HOF_CONST_THIS->get_decorator(xs...))(
BOOST_HOF_MANGLE_CAST(const T&)(BOOST_HOF_CONST_THIS->get_data(xs...)),
BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
BOOST_HOF_FORWARD(Ts)(xs)...
)
);
};
template<class D, class T>
struct decoration
: compressed_pair<D, T>
{
typedef compressed_pair<D, T> base;
BOOST_HOF_INHERIT_CONSTRUCTOR(decoration, base)
template<class... Ts>
constexpr const D& get_decorator(Ts&&... xs) const noexcept
{
return this->first(xs...);
}
template<class... Ts>
constexpr const T& get_data(Ts&&... xs) const noexcept
{
return this->second(xs...);
}
template<class F>
constexpr decorator_invoke<D, T, detail::callable_base<F>> operator()(F f) const
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(decorator_invoke<D, T, detail::callable_base<F>>, compressed_pair<D, T>, detail::callable_base<F>&&))
{
return decorator_invoke<D, T, detail::callable_base<F>>(
*this, static_cast<detail::callable_base<F>&&>(f)
);
}
};
}
template<class F>
struct decorate_adaptor : detail::callable_base<F>
{
typedef decorate_adaptor fit_rewritable1_tag;
typedef detail::callable_base<F> base;
BOOST_HOF_INHERIT_CONSTRUCTOR(decorate_adaptor, detail::callable_base<F>)
template<class... Ts>
constexpr const base& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
// TODO: Add predicate for constraints
template<class T>
constexpr detail::decoration<base, T> operator()(T x) const
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, const base&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(T, T&&))
{
return detail::decoration<base, T>(this->base_function(x), static_cast<T&&>(x));
}
};
BOOST_HOF_DECLARE_STATIC_VAR(decorate, detail::make<decorate_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,55 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
and.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_AND_H
#define BOOST_HOF_GUARD_AND_H
#include <type_traits>
#include <boost/hof/detail/using.hpp>
#include <boost/hof/detail/intrinsics.hpp>
namespace boost { namespace hof { namespace detail {
constexpr bool and_c()
{
return true;
}
template<class... Ts>
constexpr bool and_c(bool b, Ts... bs)
{
return b && and_c(bs...);
}
#ifdef _MSC_VER
template<class... Ts>
struct and_;
template<class T, class... Ts>
struct and_<T, Ts...>
: std::integral_constant<bool, (T::value && and_<Ts...>::value)>
{};
template<>
struct and_<>
: std::true_type
{};
#define BOOST_HOF_AND_UNPACK(Bs) (boost::hof::detail::and_c(Bs...))
#else
template<bool...> struct bool_seq {};
template<class... Ts>
BOOST_HOF_USING(and_, std::is_same<bool_seq<Ts::value...>, bool_seq<(Ts::value, true)...>>);
#define BOOST_HOF_AND_UNPACK(Bs) BOOST_HOF_IS_BASE_OF(boost::hof::detail::bool_seq<Bs...>, boost::hof::detail::bool_seq<(Bs || true)...>)
#endif
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,65 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
callable_base.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_CALLABLE_BASE_H
#define BOOST_HOF_GUARD_CALLABLE_BASE_H
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/apply.hpp>
#ifndef BOOST_HOF_CALLABLE_BASE_USE_TEMPLATE_ALIAS
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
#define BOOST_HOF_CALLABLE_BASE_USE_TEMPLATE_ALIAS 0
#else
#define BOOST_HOF_CALLABLE_BASE_USE_TEMPLATE_ALIAS 1
#endif
#endif
namespace boost { namespace hof { namespace detail {
template<class F>
struct non_class_function
{
F f;
BOOST_HOF_DELEGATE_CONSTRUCTOR(non_class_function, F, f)
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(apply_f, id_<F>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
boost::hof::apply(f, BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
template<class F>
struct callable_base_type
: std::conditional<(BOOST_HOF_IS_CLASS(F) && !BOOST_HOF_IS_FINAL(F) && !BOOST_HOF_IS_POLYMORPHIC(F)), F, non_class_function<F>>
{};
#if BOOST_HOF_CALLABLE_BASE_USE_TEMPLATE_ALIAS
template<class F>
using callable_base = typename callable_base_type<F>::type;
#else
template<class F>
struct callable_base
: callable_base_type<F>::type
{
typedef typename callable_base_type<F>::type base;
BOOST_HOF_INHERIT_CONSTRUCTOR(callable_base, base)
};
template<class F>
struct callable_base_type<callable_base<F>>
: callable_base_type<F>
{};
#endif
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,121 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
can_be_called.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_CAN_BE_CALLED_H
#define BOOST_HOF_GUARD_CAN_BE_CALLED_H
#include <boost/hof/config.hpp>
#include <boost/hof/detail/and.hpp>
#include <boost/hof/detail/holder.hpp>
#include <boost/hof/detail/using.hpp>
namespace boost { namespace hof { namespace detail {
#if BOOST_HOF_NO_EXPRESSION_SFINAE
struct dont_care
{
dont_care(...);
};
template<class T>
struct never_care
{
typedef dont_care type;
};
struct cant_be_called_type
{};
struct no_type
{};
template<class F>
struct is_callable_wrapper_fallback
{
template<class... Ts>
auto operator()(Ts&&...) const
-> decltype(std::declval<F>()(std::declval<Ts>()...));
};
template<class T, class U=typename std::remove_cv<typename std::remove_reference<T>::type>::type>
struct is_callable_wrapper_base
: std::conditional<BOOST_HOF_IS_CLASS(U) && !BOOST_HOF_IS_FINAL(U), U, is_callable_wrapper_fallback<U>>
{};
template<class F, class... Ts>
struct is_callable_wrapper : is_callable_wrapper_base<F>::type
{
is_callable_wrapper();
typedef cant_be_called_type const &(*pointer_to_function)(typename never_care<Ts>::type...);
operator pointer_to_function() const;
};
template<class T>
struct not_
: std::integral_constant<bool, !T::value>
{};
template<class F, class... Ts>
struct can_be_called
: not_<std::is_same<cant_be_called_type, typename std::decay<decltype(
is_callable_wrapper<F, Ts...>()(std::declval<Ts>()...)
)>::type>>
{};
template<class F, class... Ts>
struct check_args;
template<class Res, class... Ts, class... Us>
struct check_args<Res(Us...), Ts...>
: and_<std::is_convertible<Ts, Us>...>
{};
template<class Res, class... Ts, class... Us>
struct can_be_called<Res(*)(Us...), Ts...>
: std::conditional<sizeof...(Ts) == sizeof...(Us),
check_args<Res(Us...), Ts...>,
std::false_type
>::type
{};
template<class Res, class... Ts, class... Us>
struct can_be_called<Res(Us...), Ts...>
: std::conditional<sizeof...(Ts) == sizeof...(Us),
check_args<Res(Us...), Ts...>,
std::false_type
>::type
{};
#else
template<class T>
T&& called_val() noexcept;
template<class... Ts>
struct callable_args
{};
template<class F, class Args, class=void>
struct can_be_called_impl
: std::false_type
{};
template<class F, class... Args>
struct can_be_called_impl<F, callable_args<Args...>, typename detail::holder<
decltype( boost::hof::detail::called_val<F>()(boost::hof::detail::called_val<Args>()...) )
>::type>
: std::true_type
{};
template<class F, class... Ts>
BOOST_HOF_USING(can_be_called, can_be_called_impl<F, detail::callable_args<Ts...>>);
#endif
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,130 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
compressed_pair.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_COMPRESSED_PAIR_H
#define BOOST_HOF_GUARD_COMPRESSED_PAIR_H
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/config.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/alias.hpp>
#ifndef BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND
#define BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND !BOOST_HOF_HAS_EBO
#endif
namespace boost { namespace hof { namespace detail {
template<class First, class Second, class=void>
struct compressed_pair;
template<int I, class T, class U>
struct pair_tag
{};
#if BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND
template<class T, class U>
struct is_same_template
: std::false_type
{};
template<template<class...> class X, class... Ts, class... Us>
struct is_same_template<X<Ts...>, X<Us...>>
: std::true_type
{};
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
template<class T, class U>
struct is_related_template
: std::false_type
{};
#else
template<class T, class U>
struct is_related_template
: is_same_template<T, U>
{};
#endif
template<class T, class U>
struct is_related
: std::integral_constant<bool, std::is_base_of<T, U>::value || std::is_base_of<U, T>::value || is_related_template<T, U>::value>
{};
template<int I, class T, class U>
struct pair_holder
: std::conditional<(
is_related<T, U>::value),
detail::alias_empty<T, pair_tag<I, T, U>>,
detail::alias_try_inherit<T, pair_tag<I, T, U>>
>::type
{};
#else
template<int I, class T, class U>
struct pair_holder
: detail::alias_try_inherit<T, pair_tag<I, T, U>>
{};
#endif
// TODO: Empty optimizations for MSVC
template<
class First,
class Second
>
struct compressed_pair<First, Second>
: pair_holder<0, First, Second>::type, pair_holder<1, Second, First>::type
{
typedef typename pair_holder<0, First, Second>::type first_base;
typedef typename pair_holder<1, Second, First>::type second_base;
template<class X, class Y,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(First, X&&),
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Second, Y&&)
>
constexpr compressed_pair(X&& x, Y&& y)
noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(first_base, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(second_base, Y&&))
: first_base(BOOST_HOF_FORWARD(X)(x)), second_base(BOOST_HOF_FORWARD(Y)(y))
{}
BOOST_HOF_INHERIT_DEFAULT(compressed_pair, first_base, second_base)
template<class Base, class... Xs>
constexpr const Base& get_alias_base(Xs&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
template<class... Xs>
constexpr const First& first(Xs&&... xs) const noexcept
{
return boost::hof::alias_value(this->get_alias_base<first_base>(xs...), xs...);
}
template<class... Xs>
constexpr const Second& second(Xs&&... xs) const noexcept
{
return boost::hof::alias_value(this->get_alias_base<second_base>(xs...), xs...);
}
};
template<class T, class U>
constexpr compressed_pair<T, U> make_compressed_pair(T x, U y)
noexcept(BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) && BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(U))
{
return {static_cast<T&&>(x), static_cast<U&&>(y)};
}
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,74 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
constexpr_deduce.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_CONSTEXPR_DEDUCE_H
#define BOOST_HOF_GUARD_FUNCTION_CONSTEXPR_DEDUCE_H
#include <boost/hof/config.hpp>
#define BOOST_HOF_CONST_FOLD(x) (__builtin_constant_p(x) ? (x) : (x))
#ifndef BOOST_HOF_HAS_CONST_FOLD
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_HAS_CONST_FOLD 0
#elif defined(__clang__) || defined (__GNUC__)
#define BOOST_HOF_HAS_CONST_FOLD 1
#else
#define BOOST_HOF_HAS_CONST_FOLD 0
#endif
#endif
namespace boost { namespace hof {
namespace detail {
struct constexpr_deduce
{
constexpr constexpr_deduce()
{}
template<class F>
constexpr operator F() const
{
return F();
}
};
template<class T>
struct constexpr_deduce_unique
{
constexpr constexpr_deduce_unique()
{}
#if BOOST_HOF_HAS_CONST_FOLD
template<class F>
constexpr operator const F&() const
{
static_assert(BOOST_HOF_IS_EMPTY(F), "Function or lambda expression must be empty");
return BOOST_HOF_CONST_FOLD(reinterpret_cast<const F&>(static_const_var<T>()));
}
#else
template<class F>
constexpr operator F() const
{
// static_assert(std::is_default_constructible<F>::value, "Function not default constructible");
return F();
}
#endif
};
}}} // namespace boost::hof
#define BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE true ? boost::hof::detail::constexpr_deduce() :
#define BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE_UNIQUE(T) true ? boost::hof::detail::constexpr_deduce_unique<T>() :
#ifdef _MSC_VER
#define BOOST_HOF_DETAIL_MSVC_CONSTEXPR_DEDUCE BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE
#else
#define BOOST_HOF_DETAIL_MSVC_CONSTEXPR_DEDUCE
#endif
#endif

View File

@@ -0,0 +1,107 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
delgate.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_DELGATE_H
#define BOOST_HOF_GUARD_FUNCTION_DELGATE_H
#include <type_traits>
#include <utility>
#include <boost/hof/config.hpp>
#include <boost/hof/detail/and.hpp>
#include <boost/hof/detail/holder.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/using.hpp>
#include <boost/hof/detail/intrinsics.hpp>
#include <boost/hof/detail/noexcept.hpp>
#define BOOST_HOF_ENABLE_IF_CONVERTIBLE(...) \
class=typename std::enable_if<BOOST_HOF_IS_CONVERTIBLE(__VA_ARGS__)>::type
#define BOOST_HOF_ENABLE_IF_CONVERTIBLE_UNPACK(...) \
class=typename std::enable_if<BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_CONVERTIBLE(__VA_ARGS__))>::type
#define BOOST_HOF_ENABLE_IF_BASE_OF(...) \
class=typename std::enable_if<BOOST_HOF_IS_BASE_OF(__VA_ARGS__)>::type
#define BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(...) \
class=typename std::enable_if<BOOST_HOF_IS_CONSTRUCTIBLE(__VA_ARGS__)>::type
#define BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(...) \
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(__VA_ARGS__))
#define BOOST_HOF_INHERIT_DEFAULT(C, ...) \
template<bool FitPrivateEnableBool_##__LINE__=true, \
class=typename std::enable_if<FitPrivateEnableBool_##__LINE__ && boost::hof::detail::is_default_constructible_c<__VA_ARGS__>()>::type> \
constexpr C() BOOST_HOF_NOEXCEPT(boost::hof::detail::is_nothrow_default_constructible_c<__VA_ARGS__>()) {}
#define BOOST_HOF_INHERIT_DEFAULT_EMPTY(C, ...) \
template<bool FitPrivateEnableBool_##__LINE__=true, \
class=typename std::enable_if<FitPrivateEnableBool_##__LINE__ && \
boost::hof::detail::is_default_constructible_c<__VA_ARGS__>() && BOOST_HOF_IS_EMPTY(__VA_ARGS__) \
>::type> \
constexpr C() BOOST_HOF_NOEXCEPT(boost::hof::detail::is_nothrow_default_constructible_c<__VA_ARGS__>()) {}
#if BOOST_HOF_NO_TYPE_PACK_EXPANSION_IN_TEMPLATE
#define BOOST_HOF_DELGATE_PRIMITIVE_CONSTRUCTOR(constexpr_, C, T, var) \
template<class... FitXs, typename boost::hof::detail::enable_if_constructible<C, T, FitXs...>::type = 0> \
constexpr_ C(FitXs&&... fit_xs) \
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, FitXs&&...) \
: var((FitXs&&)boost::hof::forward<FitXs>(fit_xs)...) {}
#else
#define BOOST_HOF_DELGATE_PRIMITIVE_CONSTRUCTOR(constexpr_, C, T, var) \
template<class... FitXs, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, FitXs&&...)> \
constexpr_ C(FitXs&&... fit_xs) \
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, FitXs&&...) \
: var(BOOST_HOF_FORWARD(FitXs)(fit_xs)...) {}
#endif
#define BOOST_HOF_DELEGATE_CONSTRUCTOR(C, T, var) BOOST_HOF_DELGATE_PRIMITIVE_CONSTRUCTOR(constexpr, C, T, var)
// Currently its faster to use `BOOST_HOF_DELEGATE_CONSTRUCTOR` than `using
// Base::Base;`
#if 1
#define BOOST_HOF_INHERIT_CONSTRUCTOR(Derived, Base) BOOST_HOF_DELEGATE_CONSTRUCTOR(Derived, Base, Base)
#else
#define BOOST_HOF_INHERIT_CONSTRUCTOR(Derived, Base) \
using fit_inherit_base = Base; \
using fit_inherit_base::fit_inherit_base; \
Derived()=default; \
template<class FitX, BOOST_HOF_ENABLE_IF_CONVERTIBLE(FitX, Base)> \
constexpr Derived(FitX&& fit_x) : Base(BOOST_HOF_FORWARD(FitX)(fit_x)) {}
#endif
namespace boost { namespace hof {
namespace detail {
template<class... Xs>
constexpr bool is_nothrow_default_constructible_c()
{
return BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(Xs));
}
template<class... Xs>
constexpr bool is_default_constructible_c()
{
return BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(Xs));
}
template<class... Xs>
BOOST_HOF_USING(is_default_constructible, std::integral_constant<bool, is_default_constructible_c<Xs...>()>);
template<class C, class X, class... Xs>
struct enable_if_constructible
: std::enable_if<is_constructible<X, Xs&&...>::value, int>
{};
}
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,37 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
forward.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_FORWARD_H
#define BOOST_HOF_GUARD_FORWARD_H
#include <utility>
namespace boost { namespace hof {
// contexpr-friendly forwarding
template<typename T>
constexpr T&& forward(typename std::remove_reference<T>::type& t) noexcept
{ return static_cast<T&&>(t); }
template<typename T>
constexpr T&& forward(typename std::remove_reference<T>::type&& t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value, "T must not be an lvalue reference type");
return static_cast<T&&>(t);
}
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) || defined(_MSC_VER)
#define BOOST_HOF_FORWARD(...) boost::hof::forward<__VA_ARGS__>
#else
#define BOOST_HOF_FORWARD(...) static_cast<__VA_ARGS__ &&>
#endif
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,27 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
holder.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_HOLDER_H
#define BOOST_HOF_GUARD_HOLDER_H
namespace boost { namespace hof { namespace detail {
template<class... Ts>
struct holder
{
typedef void type;
};
template<template<class...> class T>
struct template_holder
{
typedef void type;
};
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,113 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
intrinsics.hpp
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_INTRINSICS_HPP
#define BOOST_HOF_GUARD_INTRINSICS_HPP
#include <type_traits>
#include <boost/hof/detail/holder.hpp>
#include <boost/hof/config.hpp>
// *** clang ***
#if defined(__clang__)
// #define BOOST_HOF_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
// #define BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(...) std::is_nothrow_constructible<__VA_ARGS__>::value
// #define BOOST_HOF_IS_CONVERTIBLE(...) std::is_convertible<__VA_ARGS__>::value
#define BOOST_HOF_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
#define BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(...) __is_nothrow_constructible(__VA_ARGS__)
#define BOOST_HOF_IS_CONVERTIBLE(...) __is_convertible_to(__VA_ARGS__)
#define BOOST_HOF_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
#define BOOST_HOF_IS_CLASS(...) __is_class(__VA_ARGS__)
#define BOOST_HOF_IS_EMPTY(...) __is_empty(__VA_ARGS__)
#define BOOST_HOF_IS_LITERAL(...) __is_literal(__VA_ARGS__)
#define BOOST_HOF_IS_POLYMORPHIC(...) __is_polymorphic(__VA_ARGS__)
#define BOOST_HOF_IS_FINAL(...) __is_final(__VA_ARGS__)
#define BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(...) __has_nothrow_copy(__VA_ARGS__)
// *** gcc ***
#elif defined(__GNUC__)
#define BOOST_HOF_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
#define BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(...) std::is_nothrow_constructible<__VA_ARGS__>::value
#define BOOST_HOF_IS_CONVERTIBLE(...) std::is_convertible<__VA_ARGS__>::value
#define BOOST_HOF_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
#define BOOST_HOF_IS_CLASS(...) __is_class(__VA_ARGS__)
#define BOOST_HOF_IS_EMPTY(...) __is_empty(__VA_ARGS__)
#define BOOST_HOF_IS_LITERAL(...) __is_literal_type(__VA_ARGS__)
#define BOOST_HOF_IS_POLYMORPHIC(...) __is_polymorphic(__VA_ARGS__)
#define BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(...) __has_nothrow_copy(__VA_ARGS__)
#if __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_IS_FINAL(...) (false)
#else
#define BOOST_HOF_IS_FINAL(...) __is_final(__VA_ARGS__)
#endif
#define BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(...) __has_nothrow_copy(__VA_ARGS__)
// *** other ***
#else
#define BOOST_HOF_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
#define BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(...) std::is_nothrow_constructible<__VA_ARGS__>::value
#define BOOST_HOF_IS_CONVERTIBLE(...) std::is_convertible<__VA_ARGS__>::value
#define BOOST_HOF_IS_BASE_OF(...) std::is_base_of<__VA_ARGS__>::value
#define BOOST_HOF_IS_CLASS(...) std::is_class<__VA_ARGS__>::value
#define BOOST_HOF_IS_EMPTY(...) std::is_empty<__VA_ARGS__>::value
#define BOOST_HOF_IS_LITERAL(...) std::is_literal_type<__VA_ARGS__>::value
#define BOOST_HOF_IS_POLYMORPHIC(...) std::is_polymorphic<__VA_ARGS__>::value
#if defined(_MSC_VER)
#define BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(...) (std::is_nothrow_copy_constructible<__VA_ARGS__>::value || std::is_reference<__VA_ARGS__>::value)
#else
#define BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(...) std::is_nothrow_copy_constructible<__VA_ARGS__>::value
#endif
#if defined(_MSC_VER)
#define BOOST_HOF_IS_FINAL(...) __is_final(__VA_ARGS__)
#else
#define BOOST_HOF_IS_FINAL(...) (false)
#endif
#endif
#if BOOST_HOF_NO_STD_DEFAULT_CONSTRUCTIBLE
#define BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(...) boost::hof::detail::is_default_constructible_helper<__VA_ARGS__>::value
#else
#define BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE BOOST_HOF_IS_CONSTRUCTIBLE
#endif
#define BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(...) BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(__VA_ARGS__, __VA_ARGS__ &&)
namespace boost { namespace hof { namespace detail {
template<class T, class=void>
struct is_default_constructible_check
: std::false_type
{};
template<class T>
struct is_default_constructible_check<T, typename holder<
decltype(T())
>::type>
: std::true_type
{};
template<class T>
struct is_default_constructible_helper
: std::conditional<(std::is_reference<T>::value),
std::false_type,
is_default_constructible_check<T>
>::type
{};
template<class T, class... Xs>
struct is_constructible
: std::is_constructible<T, Xs...>
{};
template<class T>
struct is_constructible<T>
: is_default_constructible_helper<T>
{};
}
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,43 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
join.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_DETAIL_JOIN_H
#define BOOST_HOF_GUARD_FUNCTION_DETAIL_JOIN_H
#include <boost/hof/detail/holder.hpp>
namespace boost { namespace hof { namespace detail {
template<class... Ts>
struct join_args
{};
template<template <class...> class T, class Args, class=void>
struct join_impl
{};
template<template <class...> class T, class... Args>
struct join_impl<T, join_args<Args...>, typename holder<
T<Args...>
>::type>
{ typedef T<Args...> type; };
template<template <class...> class T, class... Args>
struct join
: join_impl<T, join_args<Args...>>
{};
}}} // namespace boost::hof
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_JOIN(c, ...) typename boost::hof::detail::join<c, __VA_ARGS__>::type
#else
#define BOOST_HOF_JOIN(c, ...) c<__VA_ARGS__>
#endif
#endif

View File

@@ -0,0 +1,31 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
make.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_MAKE_H
#define BOOST_HOF_GUARD_MAKE_H
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/join.hpp>
#include <boost/hof/detail/delegate.hpp>
namespace boost { namespace hof { namespace detail {
template<template<class...> class Adaptor>
struct make
{
constexpr make() noexcept
{}
template<class... Fs, class Result=BOOST_HOF_JOIN(Adaptor, Fs...)>
constexpr Result operator()(Fs... fs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Fs&&...)
{
return Result(static_cast<Fs&&>(fs)...);
}
};
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,24 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
move.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_MOVE_H
#define BOOST_HOF_GUARD_MOVE_H
#include <utility>
namespace boost { namespace hof {
template<typename T>
constexpr typename std::remove_reference<T>::type&&
move(T&& x) noexcept
{
return static_cast<typename std::remove_reference<T>::type&&>(x);
}
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,19 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
noexcept.hpp
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_DETAIL_NOEXCEPT_HPP
#define BOOST_HOF_GUARD_DETAIL_NOEXCEPT_HPP
#include <boost/hof/config.hpp>
#if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
#define BOOST_HOF_NOEXCEPT(...) noexcept(__VA_ARGS__)
#else
#define BOOST_HOF_NOEXCEPT(...)
#endif
#endif

View File

@@ -0,0 +1,93 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
pp.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_PP_H
#define BOOST_HOF_GUARD_PP_H
#define BOOST_HOF_PP_CAT(x, y) BOOST_HOF_PP_PRIMITIVE_CAT(x, y)
#define BOOST_HOF_PP_PRIMITIVE_CAT(x, y) x ## y
#define BOOST_HOF_PP_SEQ_ITERATE(...) BOOST_HOF_PP_PRIMITIVE_SEQ_ITERATE(__VA_ARGS__)
#define BOOST_HOF_PP_PRIMITIVE_SEQ_ITERATE(...) __VA_ARGS__ ## _END
//
// BOOST_HOF_PP_NARGS returns the number of args in __VA_ARGS__
//
#define BOOST_HOF_PP_NARGS(...) \
BOOST_HOF_PP_DETAIL_NARG((__VA_ARGS__,BOOST_HOF_PP_DETAIL_RSEQ_N()))
#define BOOST_HOF_PP_DETAIL_NARG(args) \
BOOST_HOF_PP_DETAIL_ARG_N args
#define BOOST_HOF_PP_DETAIL_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define BOOST_HOF_PP_DETAIL_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
//
// BOOST_HOF_PP_IS_PAREN is used to detect if the first token is a parenthesis.
// It expands to 1 if it is, otherwise it expands to 0.
//
#define BOOST_HOF_PP_IS_PAREN(x) BOOST_HOF_PP_IS_PAREN_CHECK(BOOST_HOF_PP_IS_PAREN_PROBE x)
#define BOOST_HOF_PP_IS_PAREN_CHECK(...) BOOST_HOF_PP_IS_PAREN_CHECK_N(__VA_ARGS__,0)
#define BOOST_HOF_PP_IS_PAREN_PROBE(...) ~, 1,
#ifndef _MSC_VER
#define BOOST_HOF_PP_IS_PAREN_CHECK_N(x, n, ...) n
#else
// MSVC workarounds
#define BOOST_HOF_PP_IS_PAREN_CHECK_RES(x) x
#define BOOST_HOF_PP_IS_PAREN_CHECK_II(x, n, ...) n
#define BOOST_HOF_PP_IS_PAREN_CHECK_I(x) BOOST_HOF_PP_IS_PAREN_CHECK_RES(BOOST_HOF_PP_IS_PAREN_CHECK_II x)
#define BOOST_HOF_PP_IS_PAREN_CHECK_N(...) BOOST_HOF_PP_IS_PAREN_CHECK_I((__VA_ARGS__))
#endif
//
// BOOST_HOF_PP_IS_1 is used to detect if the first token is a 1.
// It expands to 1 if it is, otherwise it expands to 0.
//
#define BOOST_HOF_PP_IS_1(x) BOOST_HOF_PP_IS_PAREN(BOOST_HOF_PP_CAT(BOOST_HOF_PP_IS_1_PROBE_, x))
#define BOOST_HOF_PP_IS_1_PROBE_1 ()
#define BOOST_HOF_PP_ARGS_IS_SINGLE(...) BOOST_HOF_PP_IS_1(BOOST_HOF_PP_NARGS(__VA_ARGS__))
#define BOOST_HOF_PP_EMPTY(...)
#define BOOST_HOF_PP_DEFER(...) __VA_ARGS__ BOOST_HOF_PP_EMPTY()
#define BOOST_HOF_PP_OBSTRUCT(...) __VA_ARGS__ BOOST_HOF_PP_DEFER(BOOST_HOF_PP_EMPTY)()
#define BOOST_HOF_PP_EXPAND(...) __VA_ARGS__
#define BOOST_HOF_PP_IIF(c) BOOST_HOF_PP_PRIMITIVE_CAT(BOOST_HOF_PP_IIF_, c)
#define BOOST_HOF_PP_IIF_0(t, ...) __VA_ARGS__
#define BOOST_HOF_PP_IIF_1(t, ...) t
#define BOOST_HOF_PP_WALL(...) __VA_ARGS__
#define BOOST_HOF_PP_RAIL_IIF(c) BOOST_HOF_PP_PRIMITIVE_CAT(BOOST_HOF_PP_RAIL_IIF_, c)
#define BOOST_HOF_PP_RAIL_IIF_0(t, ...) __VA_ARGS__
#define BOOST_HOF_PP_RAIL_IIF_1(t, ...) t
#define BOOST_HOF_PP_RAIL(macro) \
BOOST_HOF_PP_RAIL_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_PP_WALL(())))( \
BOOST_HOF_PP_RAIL_ID BOOST_HOF_PP_OBSTRUCT()()(macro), \
macro BOOST_HOF_PP_OBSTRUCT() \
)
#define BOOST_HOF_PP_RAIL_ID() BOOST_HOF_PP_RAIL
#endif

View File

@@ -0,0 +1,19 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
recursive_constexpr_depth.hpp
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_RECURSIVE_CONSTEXPR_DEPTH_HPP
#define BOOST_HOF_GUARD_RECURSIVE_CONSTEXPR_DEPTH_HPP
#ifndef BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH
#define BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH 16
#endif
namespace boost { namespace hof {
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,26 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
remove_rvalue_reference.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_REMOVE_RVALUE_REFERENCE_H
#define BOOST_HOF_GUARD_FUNCTION_REMOVE_RVALUE_REFERENCE_H
namespace boost { namespace hof { namespace detail {
template<class T>
struct remove_rvalue_reference
{
typedef T type;
};
template<class T>
struct remove_rvalue_reference<T&&>
: remove_rvalue_reference<T>
{};
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,82 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
result_of.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_DETAIL_RESULT_OF_H
#define BOOST_HOF_GUARD_DETAIL_RESULT_OF_H
#include <boost/hof/returns.hpp>
#include <boost/hof/config.hpp>
#if BOOST_HOF_HAS_MANUAL_DEDUCTION || BOOST_HOF_NO_EXPRESSION_SFINAE
#include <boost/hof/detail/and.hpp>
#include <boost/hof/detail/holder.hpp>
#include <boost/hof/detail/can_be_called.hpp>
namespace boost { namespace hof { namespace detail {
template<class F, class Args, class=void>
struct result_of_impl {};
template<class F, class... Ts>
struct result_of_impl<
F,
holder<Ts...>,
typename std::enable_if<can_be_called<F, typename Ts::type...>::value>::type
>
{
typedef decltype(std::declval<F>()(std::declval<typename Ts::type>()...)) type;
};
}
template<class T>
struct id_
{
typedef T type;
};
template<class F, class... Ts>
struct result_of
: detail::result_of_impl<F, detail::holder<Ts...>>
{};
// template<class F, class... Ts>
// using result_of = detail::result_of_impl<F, detail::holder<Ts...>>;
// using result_of = id_<decltype(std::declval<F>()(std::declval<typename Ts::type>()...))>;
}} // namespace boost::hof
#endif
#if BOOST_HOF_NO_EXPRESSION_SFINAE
#define BOOST_HOF_SFINAE_RESULT(...) typename boost::hof::result_of<__VA_ARGS__>::type
#define BOOST_HOF_SFINAE_RETURNS(...) BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(__VA_ARGS__) { return __VA_ARGS__; }
#else
#define BOOST_HOF_SFINAE_RESULT(...) auto
#define BOOST_HOF_SFINAE_RETURNS BOOST_HOF_RETURNS
#endif
#if BOOST_HOF_HAS_MANUAL_DEDUCTION
#define BOOST_HOF_SFINAE_MANUAL_RESULT(...) typename boost::hof::result_of<__VA_ARGS__>::type
#if BOOST_HOF_HAS_COMPLETE_DECLTYPE && BOOST_HOF_HAS_MANGLE_OVERLOAD
#define BOOST_HOF_SFINAE_MANUAL_RETURNS(...) BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(__VA_ARGS__) { return (__VA_ARGS__); }
#else
#define BOOST_HOF_SFINAE_MANUAL_RETURNS(...) BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(__VA_ARGS__) { BOOST_HOF_RETURNS_RETURN(__VA_ARGS__); }
#endif
#else
#define BOOST_HOF_SFINAE_MANUAL_RESULT BOOST_HOF_SFINAE_RESULT
#define BOOST_HOF_SFINAE_MANUAL_RETURNS BOOST_HOF_SFINAE_RETURNS
#endif
#endif

View File

@@ -0,0 +1,43 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
result_type.hpp
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_RESULT_TYPE_HPP
#define BOOST_HOF_GUARD_RESULT_TYPE_HPP
#include <boost/hof/detail/holder.hpp>
#include <utility>
namespace boost { namespace hof { namespace detail {
template<class F, class=void>
struct function_result_type
{};
template<class F>
struct function_result_type<F, typename holder<
typename F::result_type
>::type>
{
typedef typename F::result_type result_type;
};
template<class F, class G, class=void>
struct compose_function_result_type
: function_result_type<F>
{};
template<class F, class G>
struct compose_function_result_type<F, G, typename holder<
decltype(std::declval<F>()(std::declval<typename G::result_type>()))
>::type>
{
typedef decltype(std::declval<F>()(std::declval<typename G::result_type>())) result_type;
};
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,46 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
seq.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_DETAIL_SEQ_H
#define BOOST_HOF_GUARD_FUNCTION_DETAIL_SEQ_H
#include <cstdlib>
namespace boost { namespace hof {
namespace detail {
template<std::size_t ...>
struct seq
{
typedef seq type;
};
template <class, class>
struct merge_seq;
template <size_t... Xs, size_t... Ys>
struct merge_seq<seq<Xs...>, seq<Ys...>>
: seq<Xs..., (sizeof...(Xs)+Ys)...>
{};
template<std::size_t N>
struct gens
: merge_seq<
typename gens<N/2>::type,
typename gens<N - N/2>::type
>
{};
template<> struct gens<0> : seq<> {};
template<> struct gens<1> : seq<0> {};
}
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,68 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
static_const_var.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_STATIC_CONST_H
#define BOOST_HOF_GUARD_STATIC_CONST_H
#include <boost/hof/detail/intrinsics.hpp>
namespace boost { namespace hof { namespace detail {
template<class T>
struct static_const_storage
{
static constexpr T value = T();
};
template<class T>
constexpr T static_const_storage<T>::value;
struct static_const_var_factory
{
constexpr static_const_var_factory()
{}
template<class T>
constexpr const T& operator=(const T&) const
{
static_assert(BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(T), "Static const variable must be default constructible");
return static_const_storage<T>::value;
}
};
}
template<class T>
constexpr const T& static_const_var()
{
return detail::static_const_storage<T>::value;
}
}} // namespace boost::hof
#if BOOST_HOF_HAS_RELAXED_CONSTEXPR || defined(_MSC_VER)
#define BOOST_HOF_STATIC_CONSTEXPR const constexpr
#else
#define BOOST_HOF_STATIC_CONSTEXPR static constexpr
#endif
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_STATIC_AUTO_REF extern __attribute__((weak)) constexpr auto
#else
#define BOOST_HOF_STATIC_AUTO_REF static constexpr auto&
#endif
// On gcc 4.6 use weak variables
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define BOOST_HOF_STATIC_CONST_VAR(name) extern __attribute__((weak)) constexpr auto name
#else
#define BOOST_HOF_STATIC_CONST_VAR(name) static constexpr auto& name = boost::hof::detail::static_const_var_factory()
#endif
#define BOOST_HOF_DECLARE_STATIC_VAR(name, ...) BOOST_HOF_STATIC_CONST_VAR(name) = __VA_ARGS__{}
#endif

View File

@@ -0,0 +1,98 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
unpack_tuple.hpp
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_UNPACK_TUPLE_HPP
#define BOOST_HOF_GUARD_UNPACK_TUPLE_HPP
#include <boost/hof/unpack_sequence.hpp>
#include <boost/hof/returns.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/seq.hpp>
#include <tuple>
#include <array>
namespace boost { namespace hof {
namespace detail {
template<class Sequence>
constexpr typename gens<std::tuple_size<Sequence>::value>::type
make_tuple_gens(const Sequence&)
{
return {};
}
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
template<std::size_t I, class Tuple>
struct tuple_element_return
: std::tuple_element<I, Tuple>
{};
template<std::size_t I, class Tuple>
struct tuple_element_return<I, Tuple&>
: std::add_lvalue_reference<typename tuple_element_return<I, Tuple>::type>
{};
template<std::size_t I, class Tuple>
struct tuple_element_return<I, Tuple&&>
: std::add_rvalue_reference<typename tuple_element_return<I, Tuple>::type>
{};
template<std::size_t I, class Tuple>
struct tuple_element_return<I, const Tuple>
: std::add_const<typename tuple_element_return<I, Tuple>::type>
{};
template< std::size_t I, class Tuple, class R = typename tuple_element_return<I, Tuple&&>::type >
R tuple_get( Tuple&& t )
{
return (R&&)(std::get<I>(boost::hof::forward<Tuple>(t)));
}
#define BOOST_HOF_UNPACK_TUPLE_GET boost::hof::detail::tuple_get
#else
#define BOOST_HOF_UNPACK_TUPLE_GET std::get
#endif
template<class F, class T, std::size_t ...N>
constexpr auto unpack_tuple(F&& f, T&& t, seq<N...>) BOOST_HOF_RETURNS
(
f(
BOOST_HOF_AUTO_FORWARD(BOOST_HOF_UNPACK_TUPLE_GET<N>(BOOST_HOF_AUTO_FORWARD(t)))...
)
);
struct unpack_tuple_apply
{
template<class F, class S>
constexpr static auto apply(F&& f, S&& t) BOOST_HOF_RETURNS
(
boost::hof::detail::unpack_tuple(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(S)(t), boost::hof::detail::make_tuple_gens(t))
);
};
}
template<class... Ts>
struct unpack_sequence<std::tuple<Ts...>>
: detail::unpack_tuple_apply
{};
template<class T, class U>
struct unpack_sequence<std::pair<T, U>>
: detail::unpack_tuple_apply
{};
template<class T, std::size_t N>
struct unpack_sequence<std::array<T, N>>
: detail::unpack_tuple_apply
{};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,29 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
unwrap.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_UNWRAP_H
#define BOOST_HOF_GUARD_UNWRAP_H
#include <type_traits>
#include <functional>
namespace boost { namespace hof { namespace detail {
template <class T>
struct unwrap_reference
{
typedef T type;
};
template <class T>
struct unwrap_reference<std::reference_wrapper<T>>
{
typedef T& type;
};
}}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,21 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
using.hpp
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_USING_HPP
#define BOOST_HOF_GUARD_USING_HPP
#include <boost/hof/config.hpp>
#if BOOST_HOF_HAS_TEMPLATE_ALIAS
#define BOOST_HOF_USING(name, ...) using name = __VA_ARGS__
#define BOOST_HOF_USING_TYPENAME(name, ...) using name = typename __VA_ARGS__
#else
#define BOOST_HOF_USING(name, ...) struct name : std::enable_if<true, __VA_ARGS__>::type {}
#define BOOST_HOF_USING_TYPENAME(name, ...) struct name : __VA_ARGS__ {}
#endif
#endif

View File

@@ -0,0 +1,86 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
eval.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_EVAL_H
#define BOOST_HOF_GUARD_EVAL_H
/// eval
/// ====
///
/// Description
/// -----------
///
/// The `eval` function will evaluate a "thunk". This can be either a nullary
/// function or it can be a unary function that takes the identity function as
/// the first parameter(which is helpful to delay compile-time checking).
/// Also, additional parameters can be passed to `eval` to delay
/// compiliation(so that result can depend on template parameters).
///
/// Synopsis
/// --------
///
/// template<class F, class... Ts>
/// constexpr auto eval(F&& f, Ts&&...);
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [EvaluatableFunctionObject](EvaluatableFunctionObject)
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// int main() {
/// assert(boost::hof::eval([]{ return 3; }) == 3);
/// }
///
/// References
/// ----------
///
/// * [POO51](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0051r2.pdf) - Proposal for C++
/// Proposal for C++ generic overload function
/// * [static_if](static_if)
/// * [Ordering evaluation of arguments](<Ordering evaluation of arguments>)
///
#include <boost/hof/always.hpp>
#include <boost/hof/identity.hpp>
#include <boost/hof/first_of.hpp>
#include <boost/hof/detail/result_of.hpp>
namespace boost { namespace hof {
namespace detail {
struct simple_eval
{
template<class F, class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(F)
operator()(F&& f, Ts&&...xs) const BOOST_HOF_SFINAE_RETURNS
(boost::hof::always_ref(f)(xs...)());
};
struct id_eval
{
template<class F, class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(F, id_<decltype(boost::hof::identity)>)
operator()(F&& f, Ts&&...xs) const BOOST_HOF_SFINAE_RETURNS
(boost::hof::always_ref(f)(xs...)(boost::hof::identity));
};
}
BOOST_HOF_DECLARE_STATIC_VAR(eval, boost::hof::first_of_adaptor<detail::simple_eval, detail::id_eval>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,244 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
first_of.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_CONDITIONAL_H
#define BOOST_HOF_GUARD_FUNCTION_CONDITIONAL_H
/// first_of
/// ========
///
/// Description
/// -----------
///
/// The `first_of` function adaptor combines several functions together. If
/// the first function can not be called, then it will try to call the next
/// function. This can be very useful when overloading functions using
/// template constraints(such as with `enable_if`).
///
/// Note: This is different than the [`match`](match.md) function adaptor, which
/// can lead to ambiguities. Instead, `first_of` will call the first function
/// that is callable, regardless if there is another function that could be
/// called as well.
///
/// Synopsis
/// --------
///
/// template<class... Fs>
/// constexpr first_of_adaptor<Fs...> first_of(Fs... fs);
///
/// Requirements
/// ------------
///
/// Fs must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <iostream>
/// using namespace boost::hof;
///
/// struct for_ints
/// {
/// void operator()(int) const
/// {
/// printf("Int\n");
/// }
/// };
///
/// struct for_floats
/// {
/// void operator()(float) const
/// {
/// printf("Float\n");
/// }
/// };
///
/// int main() {
/// first_of(for_ints(), for_floats())(3.0);
/// }
///
/// This will print `Int` because the `for_floats` function object won't ever be
/// called. Due to the conversion rules in C++, the `for_ints` function can be
/// called on floats, so it is chosen by `first_of` first, even though
/// `for_floats` is a better match.
///
/// So, the order of the functions in the `first_of_adaptor` are very important
/// to how the function is chosen.
///
/// References
/// ----------
///
/// * [POO51](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0051r2.pdf) - Proposal for C++
/// Proposal for C++ generic overload function
/// * [Conditional overloading](<Conditional overloading>)
///
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/join.hpp>
#include <boost/hof/detail/seq.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
namespace detail {
template<class F1, class F2>
struct basic_first_of_adaptor : F1, F2
{
BOOST_HOF_INHERIT_DEFAULT(basic_first_of_adaptor, F1, F2)
template<class A, class B,
BOOST_HOF_ENABLE_IF_CONVERTIBLE(A, F1),
BOOST_HOF_ENABLE_IF_CONVERTIBLE(B, F2)>
constexpr basic_first_of_adaptor(A&& f1, B&& f2)
noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F1, A&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F2, B&&))
: F1(BOOST_HOF_FORWARD(A)(f1)), F2(BOOST_HOF_FORWARD(B)(f2))
{}
template<class X,
class=typename std::enable_if<
BOOST_HOF_IS_CONVERTIBLE(X, F1) &&
BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(F2)
>::type>
constexpr basic_first_of_adaptor(X&& x)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(F1, X&&)
: F1(BOOST_HOF_FORWARD(X)(x))
{}
template<class... Ts>
struct select
: std::conditional
<
is_invocable<F1, Ts...>::value,
F1,
F2
>
{};
BOOST_HOF_RETURNS_CLASS(basic_first_of_adaptor);
template<class... Ts, class F=typename select<Ts...>::type>
constexpr BOOST_HOF_SFINAE_RESULT(typename select<Ts...>::type, id_<Ts>...)
operator()(Ts && ... xs) const
BOOST_HOF_SFINAE_RETURNS
(
BOOST_HOF_RETURNS_STATIC_CAST(const F&)(*BOOST_HOF_CONST_THIS)(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
template <class F1, class F2>
constexpr const F1& which(std::true_type, const F1& f1, const F2&) noexcept
{
return f1;
}
template <class F1, class F2>
constexpr const F2& which(std::false_type, const F1&, const F2& f2) noexcept
{
return f2;
}
template<class F1, class F2>
struct conditional_kernel : compressed_pair<F1, F2>
{
typedef compressed_pair<F1, F2> base;
BOOST_HOF_INHERIT_CONSTRUCTOR(conditional_kernel, base)
template<class... Ts>
struct select
: std::conditional
<
is_invocable<F1, Ts...>::value,
F1,
F2
>
{};
BOOST_HOF_RETURNS_CLASS(conditional_kernel);
template<class... Ts, class PickFirst=is_invocable<F1, Ts...>>
constexpr BOOST_HOF_SFINAE_RESULT(typename select<Ts...>::type, id_<Ts>...)
operator()(Ts && ... xs) const
BOOST_HOF_SFINAE_RETURNS
(
boost::hof::detail::which(
BOOST_HOF_RETURNS_CONSTRUCT(PickFirst)(),
BOOST_HOF_MANGLE_CAST(const F1&)(BOOST_HOF_CONST_THIS->first(xs...)),
BOOST_HOF_MANGLE_CAST(const F2&)(BOOST_HOF_CONST_THIS->second(xs...))
)
(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
}
template<class F, class... Fs>
struct first_of_adaptor
: detail::conditional_kernel<F, BOOST_HOF_JOIN(first_of_adaptor, Fs...) >
{
typedef first_of_adaptor fit_rewritable_tag;
typedef BOOST_HOF_JOIN(first_of_adaptor, Fs...) kernel_base;
typedef detail::conditional_kernel<F, kernel_base > base;
BOOST_HOF_INHERIT_DEFAULT(first_of_adaptor, base)
template<class X, class... Xs,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(base, X, kernel_base),
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(kernel_base, Xs...)>
constexpr first_of_adaptor(X&& f1, Xs&& ... fs)
noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, X&&, kernel_base) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(kernel_base, Xs&&...))
: base(BOOST_HOF_FORWARD(X)(f1), kernel_base(BOOST_HOF_FORWARD(Xs)(fs)...))
{}
template<class X, class... Xs,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(base, X)>
constexpr first_of_adaptor(X&& f1)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(base, X&&)
: base(BOOST_HOF_FORWARD(X)(f1))
{}
struct failure
: failure_for<F, Fs...>
{};
};
template<class F>
struct first_of_adaptor<F> : F
{
typedef first_of_adaptor fit_rewritable_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(first_of_adaptor, F);
struct failure
: failure_for<F>
{};
};
template<class F1, class F2>
struct first_of_adaptor<F1, F2>
: detail::conditional_kernel<F1, F2>
{
typedef detail::conditional_kernel<F1, F2> base;
typedef first_of_adaptor fit_rewritable_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(first_of_adaptor, base);
struct failure
: failure_for<F1, F2>
{};
};
BOOST_HOF_DECLARE_STATIC_VAR(first_of, detail::make<first_of_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,242 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
fix.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_FIX_H
#define BOOST_HOF_GUARD_FUNCTION_FIX_H
/// fix
/// ===
///
/// Description
/// -----------
///
/// The `fix` function adaptor implements a fixed-point combinator. This can be
/// used to write recursive functions.
///
/// When using `constexpr`, a function can recurse to a depth that is defined by
/// `BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH`(default is 16). There is no limitiation on
/// recursion depth for non-constexpr functions. In addition, due to the
/// eagerness of `constexpr` to instantiation templates, in some cases, an
/// explicit return type must be specified in order to avoid reaching the
/// recursion limits of the compiler. This can be accomplished using
/// [`boost::hof::result`](/include/boost/hof/result):
///
/// int r = boost::hof::result<int>(factorial)(5);
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr fix_adaptor<F> fix(F f);
///
/// Semantics
/// ---------
///
/// assert(fix(f)(xs...) == f(fix(f), xs...));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstFunctionObject](ConstFunctionObject)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// int main() {
/// auto factorial = boost::hof::fix(
/// [](auto recurse, auto x) -> decltype(x) {
/// return x == 0 ? 1 : x * recurse(x-1);
/// }
/// );
/// int r = boost::hof::result<int>(factorial)(5);
/// assert(r == 5*4*3*2*1);
/// }
///
/// References
/// ----------
///
/// * [Fixed-point combinator](https://en.wikipedia.org/wiki/Fixed-point_combinator)
/// * [Recursive](Recursive)
///
#include <boost/hof/always.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/indirect.hpp>
#include <boost/hof/result.hpp>
#include <boost/hof/detail/recursive_constexpr_depth.hpp>
namespace boost { namespace hof {
namespace detail{
template<class F>
struct compute_indirect_ref
{ typedef indirect_adaptor<const F*> type; };
template<class F>
struct compute_indirect_ref<indirect_adaptor<F*>>
{ typedef indirect_adaptor<F*> type; };
template<class F>
constexpr indirect_adaptor<const F*> make_indirect_ref(const F& f) noexcept
{
return indirect_adaptor<const F*>(&f);
}
template<class F>
constexpr indirect_adaptor<const F*> make_indirect_ref(const indirect_adaptor<F*>& f) noexcept
{
return f;
}
template<class F, class=void>
struct fix_result
{
template<class... Ts>
struct apply
{
typedef decltype(std::declval<F>()(std::declval<Ts>()...)) type;
};
};
template<class F>
struct fix_result<F, typename holder<
typename F::result_type
>::type>
{
template<class...>
struct apply
{
typedef typename F::result_type type;
};
};
template<class F, class Result, int N>
struct fix_adaptor_base : F
{
BOOST_HOF_INHERIT_CONSTRUCTOR(fix_adaptor_base, F);
typedef typename compute_indirect_ref<F>::type base_ref_type;
typedef fix_adaptor_base<base_ref_type, Result, N-1> derived;
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
template<class... Ts>
constexpr derived derived_function(Ts&&... xs) const noexcept
{
return derived(boost::hof::detail::make_indirect_ref(this->base_function(xs...)));
}
struct fix_failure
{
template<class Failure>
struct apply
{
template<class... Ts>
struct of
: Failure::template of<derived, Ts...>
{};
};
};
struct failure
: failure_map<fix_failure, F>
{};
BOOST_HOF_RETURNS_CLASS(fix_adaptor_base);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const F&, id_<derived>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...))
(
BOOST_HOF_MANGLE_CAST(derived)(BOOST_HOF_CONST_THIS->derived_function(xs...)),
BOOST_HOF_FORWARD(Ts)(xs)...
)
);
};
template<class F, class Result>
struct fix_adaptor_base<F, Result, 0> : F
{
BOOST_HOF_INHERIT_CONSTRUCTOR(fix_adaptor_base, F);
template<class... Ts>
const F& base_function(Ts&&...) const noexcept
{
return *this;
}
struct fix_failure
{
template<class Failure>
struct apply
{
template<class... Ts>
struct of
: Failure::template of<fix_adaptor_base, Ts...>
{};
};
};
struct failure
: failure_map<fix_failure, F>
{};
BOOST_HOF_RETURNS_CLASS(fix_adaptor_base);
template<class... Ts>
typename Result::template apply<fix_adaptor_base, Ts...>::type
operator()(Ts&&... xs) const
{
return this->base_function(xs...)(*this, BOOST_HOF_FORWARD(Ts)(xs)...);
}
};
}
template<class F>
struct fix_adaptor : detail::fix_adaptor_base<F, detail::fix_result<F>, BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH>
{
typedef fix_adaptor fit_rewritable1_tag;
typedef detail::fix_adaptor_base<F, detail::fix_result<F>, BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH> base;
BOOST_HOF_INHERIT_CONSTRUCTOR(fix_adaptor, base);
};
template<class Result, class F>
struct result_adaptor<Result, fix_adaptor<F>>
: fix_adaptor<result_adaptor<Result, F>>
{
typedef fix_adaptor<result_adaptor<Result, F>> base;
BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, base)
};
BOOST_HOF_DECLARE_STATIC_VAR(fix, detail::make<fix_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,107 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
flip.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_FLIP_H
#define BOOST_HOF_GUARD_FLIP_H
/// flip
/// ====
///
/// Description
/// -----------
///
/// The `flip` function adaptor swaps the first two parameters.
///
/// Synopsis
/// --------
///
/// template<class F>
/// flip_adaptor<F> flip(F f);
///
/// Semantics
/// ---------
///
/// assert(flip(f)(x, y, xs...) == f(y, x, xs...));
///
/// Requirements
/// ------------
///
/// F must be at least:
///
/// * [BinaryInvocable](BinaryInvocable)
///
/// Or:
///
/// * [Invocable](Invocable) with more than two argurments
///
/// And:
///
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// int main() {
/// int r = boost::hof::flip(boost::hof::_ - boost::hof::_)(2, 5);
/// assert(r == 3);
/// }
///
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
template<class F>
struct flip_adaptor : detail::callable_base<F>
{
typedef flip_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(flip_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return boost::hof::always_ref(*this)(xs...);
}
struct flip_failure
{
template<class Failure>
struct apply
{
template<class T, class U, class... Ts>
struct of
: Failure::template of<U, T, Ts...>
{};
};
};
struct failure
: failure_map<flip_failure, detail::callable_base<F>>
{};
BOOST_HOF_RETURNS_CLASS(flip_adaptor);
template<class T, class U, class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F>&, id_<U>, id_<T>, id_<Ts>...)
operator()(T&& x, U&& y, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
(BOOST_HOF_FORWARD(U)(y), BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
BOOST_HOF_DECLARE_STATIC_VAR(flip, detail::make<flip_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,166 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
flow.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_FLOW_H
#define BOOST_HOF_GUARD_FUNCTION_FLOW_H
/// flow
/// ====
///
/// Description
/// -----------
///
/// The `flow` function adaptor provides function composition. It is useful as
/// an alternative to using the pipe operator `|` when chaining functions. It is
/// similiar to [`compose`](compose.md) except the evaluation order is
/// reversed. So, `flow(f, g)(0)` is equivalent to `g(f(0))`.
///
///
/// Synopsis
/// --------
///
/// template<class... Fs>
/// constexpr flow_adaptor<Fs...> flow(Fs... fs);
///
/// Semantics
/// ---------
///
/// assert(flow(f, g)(xs...) == g(f(xs...)));
///
/// Requirements
/// ------------
///
/// Fs must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct increment
/// {
/// template<class T>
/// T operator()(T x) const
/// {
/// return x + 1;
/// }
/// };
///
/// struct decrement
/// {
/// template<class T>
/// T operator()(T x) const
/// {
/// return x - 1;
/// }
/// };
///
/// int main() {
/// int r = flow(increment(), decrement(), increment())(3);
/// assert(r == 4);
/// }
///
/// References
/// ----------
///
/// * [Function composition](https://en.wikipedia.org/wiki/Function_composition)
///
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/detail/join.hpp>
#include <tuple>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/result_type.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof { namespace detail {
template<class F1, class F2>
struct flow_kernel : detail::compressed_pair<detail::callable_base<F1>, detail::callable_base<F2>>, compose_function_result_type<F2, F1>
{
typedef detail::compressed_pair<detail::callable_base<F1>, detail::callable_base<F2>> base_type;
BOOST_HOF_INHERIT_CONSTRUCTOR(flow_kernel, base_type)
BOOST_HOF_RETURNS_CLASS(flow_kernel);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F2>&, result_of<const detail::callable_base<F1>&, id_<Ts>...>)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
BOOST_HOF_MANGLE_CAST(const detail::callable_base<F2>&)(BOOST_HOF_CONST_THIS->second(xs...))(
BOOST_HOF_MANGLE_CAST(const detail::callable_base<F1>&)(BOOST_HOF_CONST_THIS->first(xs...))(BOOST_HOF_FORWARD(Ts)(xs)...)
)
);
};
}
template<class F, class... Fs>
struct flow_adaptor : detail::flow_kernel<F, BOOST_HOF_JOIN(flow_adaptor, Fs...)>
{
typedef flow_adaptor fit_rewritable_tag;
typedef BOOST_HOF_JOIN(flow_adaptor, Fs...) tail;
typedef detail::flow_kernel<F, tail> base_type;
BOOST_HOF_INHERIT_DEFAULT(flow_adaptor, base_type)
template<class X, class... Xs,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(detail::callable_base<F>, X),
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(tail, Xs...)
>
constexpr flow_adaptor(X&& f1, Xs&& ... fs)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base_type, X&&, tail) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(tail, Xs&&...))
: base_type(BOOST_HOF_FORWARD(X)(f1), tail(BOOST_HOF_FORWARD(Xs)(fs)...))
{}
template<class X,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(detail::callable_base<F>, X)
>
constexpr flow_adaptor(X&& f1)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(base_type, X&&)
: base_type(BOOST_HOF_FORWARD(X)(f1))
{}
};
template<class F>
struct flow_adaptor<F> : detail::callable_base<F>
{
typedef flow_adaptor fit_rewritable_tag;
BOOST_HOF_INHERIT_DEFAULT(flow_adaptor, detail::callable_base<F>)
template<class X, BOOST_HOF_ENABLE_IF_CONVERTIBLE(X, detail::callable_base<F>)>
constexpr flow_adaptor(X&& f1)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(detail::callable_base<F>, X&&)
: detail::callable_base<F>(BOOST_HOF_FORWARD(X)(f1))
{}
};
template<class F1, class F2>
struct flow_adaptor<F1, F2>
: detail::flow_kernel<detail::callable_base<F1>, detail::callable_base<F2>>
{
typedef flow_adaptor fit_rewritable_tag;
typedef detail::flow_kernel<detail::callable_base<F1>, detail::callable_base<F2>> base_type;
BOOST_HOF_INHERIT_CONSTRUCTOR(flow_adaptor, base_type)
};
BOOST_HOF_DECLARE_STATIC_VAR(flow, detail::make<flow_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,171 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
fold.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_FOLD_H
#define BOOST_HOF_GUARD_FOLD_H
/// fold
/// ========
///
/// Description
/// -----------
///
/// The `fold` function adaptor uses a binary function to apply a
/// [fold](https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29)
/// operation to the arguments passed to the function. Additionally, an
/// optional initial state can be provided, otherwise the first argument is
/// used as the initial state.
///
/// The arguments to the binary function, take first the state and then the
/// argument.
///
/// Synopsis
/// --------
///
/// template<class F, class State>
/// constexpr fold_adaptor<F, State> fold(F f, State s);
///
/// template<class F>
/// constexpr fold_adaptor<F> fold(F f);
///
/// Semantics
/// ---------
///
/// assert(fold(f, z)() == z);
/// assert(fold(f, z)(x, xs...) == fold(f, f(z, x))(xs...));
/// assert(fold(f)(x) == x);
/// assert(fold(f)(x, y, xs...) == fold(f)(f(x, y), xs...));
///
/// Requirements
/// ------------
///
/// State must be:
///
/// * CopyConstructible
///
/// F must be:
///
/// * [BinaryInvocable](BinaryInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct max_f
/// {
/// template<class T, class U>
/// constexpr T operator()(T x, U y) const
/// {
/// return x > y ? x : y;
/// }
/// };
/// int main() {
/// assert(boost::hof::fold(max_f())(2, 3, 4, 5) == 5);
/// }
///
/// References
/// ----------
///
/// * [Fold](https://en.wikipedia.org/wiki/Fold_(higher-order_function))
/// * [Variadic sum](<Variadic sum>)
///
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof { namespace detail {
struct v_fold
{
BOOST_HOF_RETURNS_CLASS(v_fold);
template<class F, class State, class T, class... Ts>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(const v_fold&, id_<const F&>, result_of<const F&, id_<State>, id_<T>>, id_<Ts>...)
operator()(const F& f, State&& state, T&& x, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
(*BOOST_HOF_CONST_THIS)(f, f(BOOST_HOF_FORWARD(State)(state), BOOST_HOF_FORWARD(T)(x)), BOOST_HOF_FORWARD(Ts)(xs)...)
);
template<class F, class State>
constexpr State operator()(const F&, State&& state) const noexcept
{
return BOOST_HOF_FORWARD(State)(state);
}
};
}
template<class F, class State=void>
struct fold_adaptor
: detail::compressed_pair<detail::callable_base<F>, State>
{
typedef detail::compressed_pair<detail::callable_base<F>, State> base_type;
BOOST_HOF_INHERIT_CONSTRUCTOR(fold_adaptor, base_type)
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return this->first(xs...);
}
template<class... Ts>
constexpr State get_state(Ts&&... xs) const noexcept
{
return this->second(xs...);
}
BOOST_HOF_RETURNS_CLASS(fold_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(detail::v_fold, id_<const detail::callable_base<F>&>, id_<State>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
detail::v_fold()(
BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
BOOST_HOF_MANGLE_CAST(State)(BOOST_HOF_CONST_THIS->get_state(xs...)),
BOOST_HOF_FORWARD(Ts)(xs)...
)
)
};
template<class F>
struct fold_adaptor<F, void>
: detail::callable_base<F>
{
BOOST_HOF_INHERIT_CONSTRUCTOR(fold_adaptor, detail::callable_base<F>)
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(fold_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(detail::v_fold, id_<const detail::callable_base<F>&>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
detail::v_fold()(
BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
BOOST_HOF_FORWARD(Ts)(xs)...
)
)
};
BOOST_HOF_DECLARE_STATIC_VAR(fold, detail::make<fold_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,90 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
function.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_FUNCTION_H
#define BOOST_HOF_GUARD_FUNCTION_FUNCTION_H
/// BOOST_HOF_STATIC_FUNCTION
/// ===================
///
/// Description
/// -----------
///
/// The `BOOST_HOF_STATIC_FUNCTION` macro allows initializing a function object from a
/// `constexpr` expression. It uses the best practices as outlined in
/// [N4381](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html).
/// This includes using `const` to avoid global state, compile-time
/// initialization of the function object to avoid the [static initialization
/// order fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order), and an
/// external address of the function object that is the same across translation
/// units to avoid possible One-Definition-Rule(ODR) violations.
///
/// In C++17, this achieved using the `inline` keyword. However, on older
/// compilers it is initialized using a reference to a static member variable.
/// The static member variable is default constructed, as such the user variable
/// is always default constructed regardless of the expression.
///
/// By default, all functions defined with `BOOST_HOF_STATIC_FUNCTION` use the
/// [`boost::hof::reveal`](/include/boost/hof/reveal) adaptor to improve error messages.
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct sum_f
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// BOOST_HOF_STATIC_FUNCTION(sum) = sum_f();
/// BOOST_HOF_STATIC_FUNCTION(partial_sum) = boost::hof::partial(sum_f());
///
/// int main() {
/// assert(sum(1, 2) == partial_sum(1)(2));
/// }
///
#include <boost/hof/reveal.hpp>
#if !BOOST_HOF_HAS_INLINE_VARIABLES
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/detail/constexpr_deduce.hpp>
#endif
namespace boost { namespace hof {
namespace detail {
struct reveal_static_const_factory
{
constexpr reveal_static_const_factory()
{}
template<class F>
constexpr reveal_adaptor<F> operator=(const F& f) const
{
#if BOOST_HOF_HAS_INLINE_VARIABLES
#else
static_assert(BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(F), "Static functions must be default constructible");
#endif
return reveal_adaptor<F>(f);
}
};
}}} // namespace boost::hof
#if BOOST_HOF_HAS_INLINE_VARIABLES
#define BOOST_HOF_STATIC_FUNCTION(name) inline const constexpr auto name = boost::hof::detail::reveal_static_const_factory()
#else
#define BOOST_HOF_STATIC_FUNCTION(name) BOOST_HOF_STATIC_CONST_VAR(name) = BOOST_HOF_DETAIL_MSVC_CONSTEXPR_DEDUCE boost::hof::detail::reveal_static_const_factory()
#endif
#endif

View File

@@ -0,0 +1,57 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
function_param_limit.hpp
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_PARAM_LIMIT_HPP
#define BOOST_HOF_GUARD_FUNCTION_PARAM_LIMIT_HPP
/// function_param_limit
/// ====================
///
/// Description
/// -----------
///
/// The `function_param_limit` metafunction retrieves the maximum number of
/// parameters for a function. For function pointers it returns the number of
/// parameters. Everything else, it returns `SIZE_MAX`, but this can be
/// changed by annotating the function with the [`limit`](limit) decorator.
///
/// This is a type trait that inherits from `std::integral_constant`.
///
/// Synopsis
/// --------
///
/// template<class F>
/// struct function_param_limit
/// : std::integral_constant<std::size_t, ...>
/// {};
///
/// See Also
/// --------
///
/// * [Partial function evaluation](<Partial function evaluation>)
/// * [limit](limit)
///
#include <boost/hof/detail/holder.hpp>
#include <type_traits>
#include <cstdint>
namespace boost { namespace hof {
template<class F, class=void>
struct function_param_limit
: std::integral_constant<std::size_t, SIZE_MAX>
{};
template<class F>
struct function_param_limit<F, typename detail::holder<typename F::fit_function_param_limit>::type>
: F::fit_function_param_limit
{};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,72 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
identity.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_IDENTITY_H
#define BOOST_HOF_GUARD_FUNCTION_IDENTITY_H
/// identity
/// ========
///
/// Description
/// -----------
///
/// The `identity` function is an unary function object that returns whats given to it.
///
/// Semantics
/// ---------
///
/// assert(identity(x) == x);
///
/// Synopsis
/// --------
///
/// template<class T>
/// constexpr T identity(T&& x);
///
#include <utility>
#include <initializer_list>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof { namespace identity_detail {
struct identity_base
{
template<class T>
constexpr T operator()(T&& x) const
noexcept(std::is_reference<T>::value || BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T))
{
return BOOST_HOF_FORWARD(T)(x);
}
template<class T>
constexpr std::initializer_list<T>& operator()(std::initializer_list<T>& x) const noexcept
{
return x;
}
template<class T>
constexpr const std::initializer_list<T>& operator()(const std::initializer_list<T>& x) const noexcept
{
return x;
}
template<class T>
constexpr std::initializer_list<T> operator()(std::initializer_list<T>&& x) const noexcept(noexcept(std::initializer_list<T>(std::move(x))))
{
return BOOST_HOF_FORWARD(std::initializer_list<T>)(x);
}
};
}
BOOST_HOF_DECLARE_STATIC_VAR(identity, identity_detail::identity_base);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,143 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
if_.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_IF_H
#define BOOST_HOF_GUARD_IF_H
/// if
/// ==
///
/// Description
/// -----------
///
/// The `if_` function decorator makes the function callable if the boolean
/// condition is true. The `if_c` version can be used to give a boolean
/// condition directly(instead of relying on an integral constant).
///
/// When `if_` is false, the function is not callable. It is a subtitution
/// failure to call the function.
///
/// Synopsis
/// --------
///
/// template<class IntegralConstant>
/// constexpr auto if_(IntegralConstant);
///
/// template<bool B, class F>
/// constexpr auto if_c(F);
///
/// Requirements
/// ------------
///
/// IntegralConstant must be:
///
/// * IntegralConstant
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct sum_f
/// {
/// template<class T>
/// int operator()(T x, T y) const
/// {
/// return boost::hof::first_of(
/// boost::hof::if_(std::is_integral<T>())(boost::hof::_ + boost::hof::_),
/// boost::hof::always(0)
/// )(x, y);
/// }
/// };
///
/// int main() {
/// assert(sum_f()(1, 2) == 3);
/// assert(sum_f()("", "") == 0);
/// }
///
/// References
/// ----------
///
/// * [static_if](static_if)
///
#include <boost/hof/always.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
namespace detail {
template<class C, class...>
struct if_depend
: C
{};
template<bool Cond, class F>
struct if_adaptor : detail::callable_base<F>
{
BOOST_HOF_INHERIT_CONSTRUCTOR(if_adaptor, detail::callable_base<F>)
};
template<class F>
struct if_adaptor<false, F>
{
template<class... Ts>
constexpr if_adaptor(Ts&&...) noexcept
{}
};
template<bool Cond>
struct make_if_f
{
constexpr make_if_f() noexcept
{}
template<class F>
constexpr if_adaptor<Cond, F> operator()(F f) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(F, F&&)
{
return if_adaptor<Cond, F>(static_cast<F&&>(f));
}
};
struct if_f
{
constexpr if_f()
{}
template<class Cond, bool B=Cond::type::value>
constexpr make_if_f<B> operator()(Cond) const noexcept
{
return {};
}
};
}
#if BOOST_HOF_HAS_VARIABLE_TEMPLATES
template<bool B>
BOOST_HOF_STATIC_CONSTEXPR detail::make_if_f<B> if_c = {};
#else
template<bool B, class F>
constexpr detail::if_adaptor<B, F> if_c(F f) BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(F, F&&)
{
return detail::if_adaptor<B, F>(static_cast<F&&>(f));
}
#endif
BOOST_HOF_DECLARE_STATIC_VAR(if_, detail::if_f);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,155 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
implicit.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_IMPLICIT_H
#define BOOST_HOF_GUARD_FUNCTION_IMPLICIT_H
/// implicit
/// ========
///
/// Description
/// -----------
///
/// The `implicit` adaptor is a static function adaptor that uses the type
/// that the return value can be converted to, in order to determine the type
/// of the template parameter. In essence, it will deduce the type for the
/// template parameter using the type of variable the result is assigned to.
/// Since it is a static function adaptor, the function must be default
/// constructible.
///
/// Synopsis
/// --------
///
/// template<template <class...> class F>
/// class implicit<F>;
///
/// Semantics
/// ---------
///
/// assert(T(implicit<F>()(xs...)) == F<T>()(xs...));
///
/// Requirements
/// ------------
///
/// F must be a template class, that is a:
///
/// * [ConstFunctionObject](ConstFunctionObject)
/// * DefaultConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// template<class T>
/// struct auto_caster
/// {
/// template<class U>
/// T operator()(U x)
/// {
/// return T(x);
/// }
/// };
///
/// static constexpr implicit<auto_caster> auto_cast = {};
///
/// struct auto_caster_foo
/// {
/// int i;
/// explicit auto_caster_foo(int i_) : i(i_) {}
///
/// };
///
/// int main() {
/// float f = 1.5;
/// int i = auto_cast(f);
/// auto_caster_foo x = auto_cast(1);
/// assert(1 == i);
/// assert(1 == x.i);
/// }
///
#include <boost/hof/pack.hpp>
#include <boost/hof/detail/result_of.hpp>
namespace boost { namespace hof { namespace detail {
template<class F, class Pack, class X, class=void>
struct is_implicit_callable
: std::false_type
{};
#if BOOST_HOF_NO_EXPRESSION_SFINAE
template<class F, class Pack, class X>
struct is_implicit_callable<F, Pack, X, typename std::enable_if<
std::is_convertible<typename result_of<Pack, id_<F>>::type, X>::value
>::type>
: std::true_type
{};
#else
template<class F, class Pack, class X>
struct is_implicit_callable<F, Pack, X, typename std::enable_if<
std::is_convertible<decltype(std::declval<Pack>()(std::declval<F>())), X>::value
>::type>
: std::true_type
{};
#endif
}
template<template <class...> class F>
struct implicit
{
template<class Pack>
struct invoker
{
Pack p;
constexpr invoker(Pack pp) BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Pack, Pack&&)
: p(boost::hof::move(pp))
{}
template<class X, class=typename std::enable_if<detail::is_implicit_callable<F<X>, Pack, X>::value>::type>
constexpr operator X() const BOOST_HOF_NOEXCEPT(noexcept(p(F<X>())))
{
return p(F<X>());
}
#if !(defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
invoker (const invoker&) = delete;
invoker& operator= (const invoker&) = delete;
private:
friend struct implicit;
invoker (invoker&&) = default;
#endif
};
struct make_invoker
{
template<class Pack>
constexpr invoker<Pack> operator()(Pack p) const BOOST_HOF_NOEXCEPT(noexcept(invoker<Pack>(boost::hof::move(p))))
{
return invoker<Pack>(boost::hof::move(p));
}
};
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const
BOOST_HOF_RETURNS
(
BOOST_HOF_RETURNS_CONSTRUCT(make_invoker)()(boost::hof::pack_basic(BOOST_HOF_FORWARD(Ts)(xs)...))
);
};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,133 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
indirect.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_INDIRECT_H
#define BOOST_HOF_GUARD_FUNCTION_INDIRECT_H
/// indirect
/// ========
///
/// Description
/// -----------
///
/// The `indirect` function adaptor dereferences the object before calling it.
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr indirect_adaptor<F> indirect(F f);
///
/// Semantics
/// ---------
///
/// assert(indirect(f)(xs...) == (*f)(xs...));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * MoveConstructible
/// * Dereferenceable
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// #include <memory>
/// using namespace boost::hof;
///
/// struct sum
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// int r = indirect(std::make_unique<sum>())(3,2);
/// assert(r == 5);
/// }
///
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
// TODO: Support non-classes as well
template<class F>
struct indirect_adaptor : F
{
typedef indirect_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(indirect_adaptor, F);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
struct failure
: failure_for<decltype(*std::declval<F>())>
{};
BOOST_HOF_RETURNS_CLASS(indirect_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(decltype(*std::declval<F>()), id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
(*BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)))(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
template<class F>
struct indirect_adaptor<F*>
{
typedef indirect_adaptor fit_rewritable1_tag;
F* f;
constexpr indirect_adaptor() noexcept
{}
constexpr indirect_adaptor(F* x) noexcept
: f(x)
{}
template<class... Ts>
constexpr F& base_function(Ts&&...) const noexcept
{
return *f;
}
struct failure
: failure_for<F>
{};
BOOST_HOF_RETURNS_CLASS(indirect_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(F, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
(BOOST_HOF_MANGLE_CAST(F&)(BOOST_HOF_CONST_THIS->base_function(xs...)))(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
BOOST_HOF_DECLARE_STATIC_VAR(indirect, detail::make<indirect_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,200 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
infix.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_INFIX_H
#define BOOST_HOF_GUARD_FUNCTION_INFIX_H
/// infix
/// =====
///
/// Description
/// -----------
///
/// The `infix` function adaptor allows the function to be used as an infix
/// operator. The operator must be placed inside the angle brackets(ie `<`
/// and `>`).
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr infix_adaptor<F> infix(F f);
///
/// Semantics
/// ---------
///
/// assert(x <infix(f)> y == f(x, y));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [BinaryInvocable](BinaryInvocable)
/// * MoveConstructible
///
/// Operator precedence
/// -------------------
///
/// Infix operators have the precedence of relational operators. This means
/// operators such as `+` or `*` have higher precedence:
///
/// assert((x + y <infix(f)> z) == ((x + y) <infix(f)> z));
/// assert((x * y <infix(f)> z) == ((x * y) <infix(f)> z));
///
/// However, operators such as `|` or `==` have lower precedence::
///
/// assert((x | y <infix(f)> z) == (x | (y <infix(f)> z)));
/// assert((x == y <infix(f)> z) == (x == (y <infix(f)> z)));
///
/// Also, infix operators have left-to-right associativity:
///
/// assert(x <infix(f)> y <infix(g)> z == ((x <infix(f)> y) <infix(g)> z));
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct plus_f
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// constexpr infix_adaptor<plus_f> plus = {};
/// int r = 3 <plus> 2;
/// assert(r == 5);
/// }
///
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
namespace detail{
template<class T, class F>
struct postfix_adaptor : F
{
T x;
template<class X, class XF>
constexpr postfix_adaptor(X&& xp, XF&& fp)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F, XF&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(T, X&&))
: F(BOOST_HOF_FORWARD(XF)(fp)), x(BOOST_HOF_FORWARD(X)(xp))
{}
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(postfix_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const F&, id_<T&&>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
(BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)))(BOOST_HOF_RETURNS_C_CAST(T&&)(BOOST_HOF_CONST_THIS->x), BOOST_HOF_FORWARD(Ts)(xs)...)
);
template<class A>
constexpr BOOST_HOF_SFINAE_RESULT(const F&, id_<T&&>, id_<A>)
operator>(A&& a) const BOOST_HOF_SFINAE_RETURNS
(
(BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(a)))(BOOST_HOF_RETURNS_C_CAST(T&&)(BOOST_HOF_CONST_THIS->x), BOOST_HOF_FORWARD(A)(a))
);
};
template<class T, class F>
constexpr postfix_adaptor<T, F> make_postfix_adaptor(T&& x, F f)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(postfix_adaptor<T, F>, T&&, F&&)
{
return postfix_adaptor<T, F>(BOOST_HOF_FORWARD(T)(x), static_cast<F&&>(f));
}
}
template<class F>
struct infix_adaptor : detail::callable_base<F>
{
typedef infix_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(infix_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
template<class... Ts>
constexpr const detail::callable_base<F>& infix_base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(infix_adaptor);
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)))(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
template<class T, class F>
constexpr auto operator<(T&& x, const infix_adaptor<F>& i) BOOST_HOF_RETURNS
(detail::make_postfix_adaptor(BOOST_HOF_FORWARD(T)(x), boost::hof::move(i.base_function(x))));
// TODO: Operators for static_
namespace detail {
template<class F>
struct static_function_wrapper;
// Operators for static_function_wrapper adaptor
template<class T, class F>
auto operator<(T&& x, const boost::hof::detail::static_function_wrapper<F>& f) BOOST_HOF_RETURNS
(
detail::make_postfix_adaptor(BOOST_HOF_FORWARD(T)(x), boost::hof::move(f.base_function().infix_base_function()))
);
template<class F>
struct static_default_function;
// Operators for static_default_function adaptor
template<class T, class F>
auto operator<(T&& x, const boost::hof::detail::static_default_function<F>&) BOOST_HOF_RETURNS
(
detail::make_postfix_adaptor(BOOST_HOF_FORWARD(T)(x), boost::hof::move(F().infix_base_function()))
);
}
// This overload is needed for gcc
template<class T, class F>
constexpr auto operator<(T&& x, const boost::hof::reveal_adaptor<F>& f) BOOST_HOF_RETURNS
(
detail::make_postfix_adaptor(BOOST_HOF_FORWARD(T)(x), f.infix_base_function())
);
BOOST_HOF_DECLARE_STATIC_VAR(infix, detail::make<infix_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,72 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
is_invocable.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_IS_CALLABLE_H
#define BOOST_HOF_GUARD_IS_CALLABLE_H
/// is_invocable
/// ===========
///
/// Description
/// -----------
///
/// The `is_invocable` metafunction checks if the function is callable with
/// certain parameters.
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [Invocable](Invocable)
///
/// Synopsis
/// --------
///
/// template<class F, class... Ts>
/// struct is_invocable;
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// using namespace boost::hof;
///
/// struct is_invocable_class
/// {
/// void operator()(int) const
/// {
/// }
/// };
/// static_assert(is_invocable<is_invocable_class, int>(), "Not callable");
///
/// int main() {}
///
#include <boost/hof/detail/can_be_called.hpp>
#include <boost/hof/apply.hpp>
namespace boost { namespace hof {
template<class F, class... Ts>
struct is_invocable
: detail::can_be_called<detail::apply_f, F, Ts...>
{};
template<class F, class... Ts, class... Us>
struct is_invocable<F(Ts...), Us...>
{
static_assert(!std::is_same<F, F>::value,
"The is_invocable<F(Args...)> form is not supported because it is problematic."
"Please use is_invocable<F, Args...> instead."
);
};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,115 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
is_unpackable.hpp
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_IS_UNPACKABLE_HPP
#define BOOST_HOF_GUARD_IS_UNPACKABLE_HPP
/// is_unpackable
/// =============
///
/// This is a trait that can be used to detect whether the type can be called
/// with `unpack`.
///
/// Synopsis
/// --------
///
/// template<class T>
/// struct is_unpackable;
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// int main() {
/// static_assert(boost::hof::is_unpackable<std::tuple<int>>::value, "Failed");
/// }
///
#include <boost/hof/unpack_sequence.hpp>
#include <boost/hof/is_invocable.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/detail/unpack_tuple.hpp>
namespace boost { namespace hof {
namespace detail {
struct unpack_impl_f
{
template<class F, class Sequence>
constexpr auto operator()(F&& f, Sequence&& s) const BOOST_HOF_RETURNS
(
boost::hof::unpack_sequence<typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type>::
apply(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(Sequence)(s))
);
};
BOOST_HOF_DECLARE_STATIC_VAR(unpack_impl, unpack_impl_f);
#if BOOST_HOF_CHECK_UNPACK_SEQUENCE
struct private_unpack_type {};
template<class Sequence>
struct unpack_impl_result
{
static_assert(boost::hof::is_invocable<unpack_impl_f, decltype(boost::hof::always(private_unpack_type())), Sequence>::value,
"Unpack is invalid for this sequence. The function used to unpack this sequence is not callable."
);
typedef decltype(boost::hof::detail::unpack_impl(boost::hof::always(private_unpack_type()), std::declval<Sequence>())) type;
};
template<class Sequence>
struct is_proper_sequence
: std::is_same<
private_unpack_type,
typename unpack_impl_result<Sequence>::type
>
{};
#endif
template<class Sequence, class=void>
struct is_unpackable_impl
: std::true_type
{
#if BOOST_HOF_CHECK_UNPACK_SEQUENCE
static_assert(is_proper_sequence<Sequence>::value,
"Unpack is invalid for this sequence. The function used to unpack this sequence does not invoke the function."
);
#endif
};
template<class Sequence>
struct is_unpackable_impl<Sequence, typename detail::holder<
typename unpack_sequence<Sequence>::not_unpackable
>::type>
: std::false_type
{};
}
template<class Sequence>
struct is_unpackable
: detail::is_unpackable_impl<
typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type
>
{
#if BOOST_HOF_CHECK_UNPACK_SEQUENCE
typedef detail::is_unpackable_impl<
typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type
> base;
typedef std::conditional<base::value, detail::is_proper_sequence<Sequence>, std::true_type> check;
static_assert(check::type::value,
"Unpack is invalid for this sequence. The function used to unpack this sequence does not invoke the function."
);
#endif
};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,244 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
lambda.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_LAMBDA_H
#define BOOST_HOF_GUARD_FUNCTION_LAMBDA_H
/// BOOST_HOF_STATIC_LAMBDA
/// =================
///
/// Description
/// -----------
///
/// The `BOOST_HOF_STATIC_LAMBDA` macro allows initializing non-capturing lambdas at
/// compile-time in a `constexpr` expression.
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// const constexpr auto add_one = BOOST_HOF_STATIC_LAMBDA(int x)
/// {
/// return x + 1;
/// };
///
/// int main() {
/// assert(3 == add_one(2));
/// }
///
/// BOOST_HOF_STATIC_LAMBDA_FUNCTION
/// ==========================
///
/// Description
/// -----------
///
/// The `BOOST_HOF_STATIC_LAMBDA_FUNCTION` macro allows initializing a global
/// function object that contains non-capturing lambdas. It also ensures that
/// the global function object has a unique address across translation units.
/// This helps prevent possible ODR-violations.
///
/// By default, all functions defined with `BOOST_HOF_STATIC_LAMBDA_FUNCTION` use
/// the `boost::hof::reveal` adaptor to improve error messages.
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// BOOST_HOF_STATIC_LAMBDA_FUNCTION(add_one) = [](int x)
/// {
/// return x + 1;
/// };
/// int main() {
/// assert(3 == add_one(2));
/// }
///
#include <boost/hof/config.hpp>
// TODO: Move this to a detail header
#if !BOOST_HOF_HAS_CONSTEXPR_LAMBDA || !BOOST_HOF_HAS_INLINE_LAMBDAS
#include <type_traits>
#include <utility>
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/constexpr_deduce.hpp>
#include <boost/hof/function.hpp>
#ifndef BOOST_HOF_REWRITE_STATIC_LAMBDA
#ifdef _MSC_VER
#define BOOST_HOF_REWRITE_STATIC_LAMBDA 1
#else
#define BOOST_HOF_REWRITE_STATIC_LAMBDA 0
#endif
#endif
namespace boost { namespace hof {
namespace detail {
template<class F>
struct static_function_wrapper
{
// Default constructor necessary for MSVC
constexpr static_function_wrapper()
{}
static_assert(BOOST_HOF_IS_EMPTY(F), "Function or lambda expression must be empty");
struct failure
: failure_for<F>
{};
template<class... Ts>
const F& base_function(Ts&&...) const
{
return reinterpret_cast<const F&>(*this);
}
BOOST_HOF_RETURNS_CLASS(static_function_wrapper);
template<class... Ts>
BOOST_HOF_SFINAE_RESULT(const F&, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
BOOST_HOF_RETURNS_REINTERPRET_CAST(const F&)(*BOOST_HOF_CONST_THIS)(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
struct static_function_wrapper_factor
{
constexpr static_function_wrapper_factor()
{}
template<class F>
constexpr static_function_wrapper<F> operator= (const F&) const
{
// static_assert(std::is_literal_type<static_function_wrapper<F>>::value, "Function wrapper not a literal type");
return {};
}
};
#if BOOST_HOF_REWRITE_STATIC_LAMBDA
template<class T, class=void>
struct is_rewritable
: std::false_type
{};
template<class T>
struct is_rewritable<T, typename detail::holder<
typename T::fit_rewritable_tag
>::type>
: std::is_same<typename T::fit_rewritable_tag, T>
{};
template<class T, class=void>
struct is_rewritable1
: std::false_type
{};
template<class T>
struct is_rewritable1<T, typename detail::holder<
typename T::fit_rewritable1_tag
>::type>
: std::is_same<typename T::fit_rewritable1_tag, T>
{};
template<class T, class=void>
struct rewrite_lambda;
template<template<class...> class Adaptor, class... Ts>
struct rewrite_lambda<Adaptor<Ts...>, typename std::enable_if<
is_rewritable<Adaptor<Ts...>>::value
>::type>
{
typedef Adaptor<typename rewrite_lambda<Ts>::type...> type;
};
template<template<class...> class Adaptor, class T, class... Ts>
struct rewrite_lambda<Adaptor<T, Ts...>, typename std::enable_if<
is_rewritable1<Adaptor<T, Ts...>>::value
>::type>
{
typedef Adaptor<typename rewrite_lambda<T>::type, Ts...> type;
};
template<class T>
struct rewrite_lambda<T, typename std::enable_if<
std::is_empty<T>::value &&
!is_rewritable<T>::value &&
!is_rewritable1<T>::value
>::type>
{
typedef static_function_wrapper<T> type;
};
template<class T>
struct rewrite_lambda<T, typename std::enable_if<
!std::is_empty<T>::value &&
!is_rewritable<T>::value &&
!is_rewritable1<T>::value
>::type>
{
typedef T type;
};
#endif
template<class T>
struct reveal_static_lambda_function_wrapper_factor
{
constexpr reveal_static_lambda_function_wrapper_factor()
{}
#if BOOST_HOF_REWRITE_STATIC_LAMBDA
template<class F>
constexpr reveal_adaptor<typename rewrite_lambda<F>::type>
operator=(const F&) const
{
return reveal_adaptor<typename rewrite_lambda<F>::type>();
}
#elif BOOST_HOF_HAS_CONST_FOLD
template<class F>
constexpr const reveal_adaptor<F>& operator=(const F&) const
{
return reinterpret_cast<const reveal_adaptor<F>&>(static_const_var<T>());
}
#else
template<class F>
constexpr reveal_adaptor<static_function_wrapper<F>> operator=(const F&) const
{
return {};
}
#endif
};
}}} // namespace boost::hof
#endif
#if BOOST_HOF_HAS_CONSTEXPR_LAMBDA
#define BOOST_HOF_STATIC_LAMBDA []
#else
#define BOOST_HOF_DETAIL_MAKE_STATIC BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE boost::hof::detail::static_function_wrapper_factor()
#define BOOST_HOF_STATIC_LAMBDA BOOST_HOF_DETAIL_MAKE_STATIC = []
#endif
#if BOOST_HOF_HAS_INLINE_LAMBDAS
#define BOOST_HOF_STATIC_LAMBDA_FUNCTION BOOST_HOF_STATIC_FUNCTION
#else
#define BOOST_HOF_DETAIL_MAKE_REVEAL_STATIC(T) BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE_UNIQUE(T) boost::hof::detail::reveal_static_lambda_function_wrapper_factor<T>()
#define BOOST_HOF_STATIC_LAMBDA_FUNCTION(name) \
struct fit_private_static_function_ ## name {}; \
BOOST_HOF_STATIC_AUTO_REF name = BOOST_HOF_DETAIL_MAKE_REVEAL_STATIC(fit_private_static_function_ ## name)
#endif
#endif

View File

@@ -0,0 +1,299 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
lazy.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_LAZY_H
#define BOOST_HOF_GUARD_FUNCTION_LAZY_H
/// lazy
/// ====
///
/// Description
/// -----------
///
/// The `lazy` function adaptor returns a function object call wrapper for a
/// function. Calling this wrapper is equivalent to invoking the function. It
/// is a simple form of lambda expressions, but is constexpr friendly. By
/// default, `lazy` captures all of its variables by value, just like `bind`.
/// `std::ref` can be used to capture references instead.
///
/// Ultimately, calling `lazy(f)(x)` is the equivalent to calling
/// `std::bind(f, x)` except the lazy version can be called in a constexpr
/// context, as well. The `lazy` adaptor is compatible with `std::bind`, so
/// most of the time `lazy` and `std::bind` can be used interchangeably.
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr lazy_adaptor<F> lazy(F f);
///
/// Semantics
/// ---------
///
/// assert(lazy(f)(xs...) == std::bind(f, xs...))
/// assert(lazy(f)(xs...)() == f(xs...))
/// assert(lazy(f)(_1)(x) == f(x))
/// assert(lazy(f)(lazy(g)(_1))(x) == f(g(x)))
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// int main() {
/// auto add = [](auto x, auto y) { return x+y; };
/// auto increment = lazy(add)(_1, 1);
/// assert(increment(5) == 6);
/// }
///
/// References
/// ----------
///
/// * [std::bind](http://en.cppreference.com/w/cpp/utility/functional/bind)
///
#include <boost/hof/arg.hpp>
#include <boost/hof/first_of.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/static.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/pack.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <functional>
#include <type_traits>
namespace boost { namespace hof {
namespace detail {
struct placeholder_transformer
{
template<class T, typename std::enable_if<(std::is_placeholder<T>::value > 0), int>::type = 0>
constexpr detail::make_args_f<std::size_t, std::is_placeholder<T>::value> operator()(const T&) const noexcept
{
return {};
}
};
struct bind_transformer
{
template<class T, typename std::enable_if<std::is_bind_expression<T>::value, int>::type = 0>
constexpr const T& operator()(const T& x) const noexcept
{
return x;
}
};
struct ref_transformer
{
template<class T>
constexpr auto operator()(std::reference_wrapper<T> x) const
BOOST_HOF_SFINAE_RETURNS(boost::hof::always_ref(x.get()));
};
struct id_transformer
{
template<class T>
constexpr auto operator()(T&& x) const
BOOST_HOF_SFINAE_RETURNS(always_detail::always_base<T>(BOOST_HOF_FORWARD(T)(x)));
};
BOOST_HOF_DECLARE_STATIC_VAR(pick_transformer, first_of_adaptor<placeholder_transformer, bind_transformer, ref_transformer, id_transformer>);
template<class T, class Pack>
constexpr auto lazy_transform(T&& x, const Pack& p) BOOST_HOF_RETURNS
(
p(boost::hof::detail::pick_transformer(BOOST_HOF_FORWARD(T)(x)))
);
template<class F, class Pack>
struct lazy_unpack
{
const F& f;
const Pack& p;
constexpr lazy_unpack(const F& fp, const Pack& pp) noexcept
: f(fp), p(pp)
{}
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
f(lazy_transform(BOOST_HOF_FORWARD(Ts)(xs), p)...)
);
};
template<class F, class Pack>
constexpr lazy_unpack<F, Pack> make_lazy_unpack(const F& f, const Pack& p) noexcept
{
return lazy_unpack<F, Pack>(f, p);
}
template<class F, class Pack>
struct lazy_invoker
: detail::compressed_pair<F, Pack>
{
typedef detail::compressed_pair<F, Pack> base_type;
typedef lazy_invoker fit_rewritable1_tag;
#ifdef _MSC_VER
BOOST_HOF_INHERIT_CONSTRUCTOR(lazy_invoker, base_type)
#else
BOOST_HOF_INHERIT_DEFAULT_EMPTY(lazy_invoker, base_type)
template<class X, class Y,
BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(base_type, X&&, Y&&)
>
constexpr lazy_invoker(X&& x, Y&& y)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(base_type, X&&, Y&&)
: base_type(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(Y)(y))
{}
#endif
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const noexcept
{
return this->first(xs...);
}
template<class... Ts>
constexpr const Pack& get_pack(Ts&&... xs) const noexcept
{
return this->second(xs...);
}
BOOST_HOF_RETURNS_CLASS(lazy_invoker);
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(xs...))(
boost::hof::detail::make_lazy_unpack(
BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)
)
)
);
};
template<class F, class Pack>
constexpr lazy_invoker<F, Pack> make_lazy_invoker(F f, Pack pack)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(lazy_invoker<F, Pack>, F&&, Pack&&)
{
return lazy_invoker<F, Pack>(static_cast<F&&>(f), static_cast<Pack&&>(pack));
}
template<class F>
struct lazy_nullary_invoker : F
{
BOOST_HOF_INHERIT_CONSTRUCTOR(lazy_nullary_invoker, F);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(lazy_nullary_invoker);
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...))()
);
};
template<class F>
constexpr lazy_nullary_invoker<F> make_lazy_nullary_invoker(F f)
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(lazy_nullary_invoker<F>, F&&)
{
return lazy_nullary_invoker<F>(static_cast<F&&>(f));
}
}
template<class F>
struct lazy_adaptor : detail::callable_base<F>
{
BOOST_HOF_INHERIT_CONSTRUCTOR(lazy_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(lazy_adaptor);
template<class T, class... Ts>
constexpr auto operator()(T x, Ts... xs) const BOOST_HOF_RETURNS
(
boost::hof::detail::make_lazy_invoker(BOOST_HOF_RETURNS_C_CAST(detail::callable_base<F>&&)(BOOST_HOF_CONST_THIS->base_function(x, xs...)),
boost::hof::pack_basic(BOOST_HOF_RETURNS_STATIC_CAST(T&&)(x), BOOST_HOF_RETURNS_STATIC_CAST(Ts&&)(xs)...))
);
// Workaround for gcc 4.7
template<class Unused=int>
constexpr detail::lazy_nullary_invoker<F> operator()() const
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(
boost::hof::detail::make_lazy_nullary_invoker(BOOST_HOF_RETURNS_C_CAST(detail::callable_base<F>&&)(
BOOST_HOF_CONST_THIS->base_function(BOOST_HOF_RETURNS_CONSTRUCT(Unused)())
))
)
{
return boost::hof::detail::make_lazy_nullary_invoker((detail::callable_base<F>&&)(
this->base_function(Unused())
));
}
// TODO: Overloads to use with ref qualifiers
// template<class... Ts>
// constexpr auto operator()(Ts... xs) const& BOOST_HOF_RETURNS
// (
// boost::hof::detail::make_lazy_invoker(this->base_function(xs...),
// pack(boost::hof::move(xs)...))
// );
// template<class... Ts>
// constexpr auto operator()(Ts... xs) && BOOST_HOF_RETURNS
// (
// boost::hof::detail::make_lazy_invoker((F&&)this->base_function(xs...),
// pack(boost::hof::move(xs)...))
// );
};
BOOST_HOF_DECLARE_STATIC_VAR(lazy, detail::make<lazy_adaptor>);
}} // namespace boost::hof
namespace std {
template<class F, class Pack>
struct is_bind_expression<boost::hof::detail::lazy_invoker<F, Pack>>
: std::true_type
{};
template<class F>
struct is_bind_expression<boost::hof::detail::lazy_nullary_invoker<F>>
: std::true_type
{};
}
#endif

View File

@@ -0,0 +1,110 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
lift.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_LIFT_H
#define BOOST_HOF_GUARD_FUNCTION_LIFT_H
/// BOOST_HOF_LIFT
/// ========
///
/// Description
/// -----------
///
/// The macros `BOOST_HOF_LIFT` and `BOOST_HOF_LIFT_CLASS` provide a lift operator that
/// will wrap a template function in a function object so it can be passed to
/// higher-order functions. The `BOOST_HOF_LIFT` macro will wrap the function using
/// a generic lambda. As such, it will not preserve `constexpr`. The
/// `BOOST_HOF_LIFT_CLASS` can be used to declare a class that will wrap function.
/// This will preserve `constexpr` and it can be used on older compilers that
/// don't support generic lambdas yet.
///
/// Limitation
/// ----------
///
/// In C++14, `BOOST_HOF_LIFT` doesn't support `constexpr` due to using a generic
/// lambda. Instead, `BOOST_HOF_LIFT_CLASS` can be used. In C++17, there is no such
/// limitation.
///
/// Synopsis
/// --------
///
/// // Wrap the function in a generic lambda
/// #define BOOST_HOF_LIFT(...)
///
/// // Declare a class named `name` that will forward to the function
/// #define BOOST_HOF_LIFT_CLASS(name, ...)
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// #include <algorithm>
///
/// // Declare the class `max_f`
/// BOOST_HOF_LIFT_CLASS(max_f, std::max);
///
/// int main() {
/// auto my_max = BOOST_HOF_LIFT(std::max);
/// assert(my_max(3, 4) == std::max(3, 4));
/// assert(max_f()(3, 4) == std::max(3, 4));
/// }
///
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/returns.hpp>
#include <boost/hof/lambda.hpp>
#include <boost/hof/detail/forward.hpp>
namespace boost { namespace hof { namespace detail {
template<class F, class NoExcept>
struct lift_noexcept : F
{
BOOST_HOF_INHERIT_CONSTRUCTOR(lift_noexcept, F);
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const
noexcept(decltype(std::declval<NoExcept>()(BOOST_HOF_FORWARD(Ts)(xs)...)){})
-> decltype(std::declval<F>()(BOOST_HOF_FORWARD(Ts)(xs)...))
{ return F(*this)(BOOST_HOF_FORWARD(Ts)(xs)...);}
};
template<class F, class NoExcept>
constexpr lift_noexcept<F, NoExcept> make_lift_noexcept(F f, NoExcept)
{
return {f};
}
}
}} // namespace boost::hof
#define BOOST_HOF_LIFT_IS_NOEXCEPT(...) std::integral_constant<bool, noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))>{}
#if defined (_MSC_VER)
#define BOOST_HOF_LIFT(...) (BOOST_HOF_STATIC_LAMBDA { BOOST_HOF_LIFT_CLASS(fit_local_lift_t, __VA_ARGS__); return fit_local_lift_t(); }())
#elif defined (__clang__)
#define BOOST_HOF_LIFT(...) (boost::hof::detail::make_lift_noexcept( \
BOOST_HOF_STATIC_LAMBDA(auto&&... xs) \
-> decltype((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)) \
{ return (__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...); }, \
BOOST_HOF_STATIC_LAMBDA(auto&&... xs) { return BOOST_HOF_LIFT_IS_NOEXCEPT((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)); } \
))
#else
#define BOOST_HOF_LIFT(...) (BOOST_HOF_STATIC_LAMBDA(auto&&... xs) BOOST_HOF_RETURNS((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)))
#endif
#define BOOST_HOF_LIFT_CLASS(name, ...) \
struct name \
{ \
template<class... Ts> \
constexpr auto operator()(Ts&&... xs) const \
BOOST_HOF_RETURNS((__VA_ARGS__)(BOOST_HOF_FORWARD(Ts)(xs)...)) \
}
#endif

View File

@@ -0,0 +1,142 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
limit.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_LIMIT_H
#define BOOST_HOF_GUARD_LIMIT_H
/// limit
/// =====
///
/// Description
/// -----------
///
/// The `limit` function decorator annotates the function with the max number
/// of parameters. The `limit_c` version can be used to give the max number
/// directly(instead of relying on an integral constant). The parameter limit
/// can be read by using the [`function_param_limit`](function_param_limit)
/// trait. Using `limit` is useful to improve error reporting with partially
/// evaluated functions.
///
/// Synopsis
/// --------
///
/// template<class IntegralConstant>
/// constexpr auto limit(IntegralConstant);
///
/// template<std::size_t N, class F>
/// constexpr auto limit_c(F);
///
/// Requirements
/// ------------
///
/// IntegralConstant must be:
///
/// * IntegralConstant
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct sum_f
/// {
/// template<class T>
/// int operator()(T x, T y) const
/// {
/// return x+y;
/// }
/// };
/// BOOST_HOF_STATIC_FUNCTION(sum) = limit_c<2>(sum_f());
///
/// int main() {
/// assert(3 == sum(1, 2));
/// }
///
/// See Also
/// --------
///
/// * [Partial function evaluation](<Partial function evaluation>)
/// * [function_param_limit](function_param_limit)
///
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/function_param_limit.hpp>
namespace boost { namespace hof {
namespace detail {
// TODO: Make this work with fit_rewritable1_tag
template<std::size_t N, class F>
struct limit_adaptor : detail::callable_base<F>
{
typedef std::integral_constant<std::size_t, N> fit_function_param_limit;
BOOST_HOF_INHERIT_CONSTRUCTOR(limit_adaptor, detail::callable_base<F>)
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(limit_adaptor);
template<class... Ts, class=typename std::enable_if<(sizeof...(Ts) <= N)>::type>
constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F>&, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
template<std::size_t N>
struct make_limit_f
{
constexpr make_limit_f()
{}
template<class F>
constexpr limit_adaptor<N, F> operator()(F f) const
{
return limit_adaptor<N, F>(static_cast<F&&>(f));
}
};
struct limit_f
{
template<class IntegralConstant, std::size_t N=IntegralConstant::type::value>
constexpr make_limit_f<N> operator()(IntegralConstant) const
{
return {};
}
};
}
template<std::size_t N, class F>
constexpr detail::limit_adaptor<N, F> limit_c(F f)
{
return detail::limit_adaptor<N, F>(static_cast<F&&>(f));
}
BOOST_HOF_DECLARE_STATIC_VAR(limit, detail::limit_f);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,121 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
match.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_OVERLOAD_H
#define BOOST_HOF_GUARD_FUNCTION_OVERLOAD_H
/// match
/// =====
///
/// Description
/// -----------
///
/// The `match` function adaptor combines several functions together and
/// resolves which one should be called by using C++ overload resolution. This
/// is different than the [`first_of`](/include/boost/hof/conditional) adaptor which resolves
/// them based on order.
///
/// Synopsis
/// --------
///
/// template<class... Fs>
/// constexpr match_adaptor<Fs...> match(Fs...fs);
///
/// Requirements
/// ------------
///
/// Fs must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// using namespace boost::hof;
///
/// struct int_class
/// {
/// int operator()(int) const
/// {
/// return 1;
/// }
/// };
///
/// struct foo
/// {};
///
/// struct foo_class
/// {
/// foo operator()(foo) const
/// {
/// return foo();
/// }
/// };
///
/// typedef match_adaptor<int_class, foo_class> fun;
///
/// static_assert(std::is_same<int, decltype(fun()(1))>::value, "Failed match");
/// static_assert(std::is_same<foo, decltype(fun()(foo()))>::value, "Failed match");
///
/// int main() {}
///
/// References
/// ----------
///
/// * [POO51](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0051r2.pdf) - Proposal for C++
/// Proposal for C++ generic overload function
///
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
template<class...Fs> struct match_adaptor;
template<class F, class...Fs>
struct match_adaptor<F, Fs...> : detail::callable_base<F>, match_adaptor<Fs...>
{
typedef match_adaptor<Fs...> base;
typedef match_adaptor fit_rewritable_tag;
struct failure
: failure_for<detail::callable_base<F>, Fs...>
{};
BOOST_HOF_INHERIT_DEFAULT(match_adaptor, detail::callable_base<F>, base);
template<class X, class... Xs, BOOST_HOF_ENABLE_IF_CONVERTIBLE(X, detail::callable_base<F>), BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(base, Xs...)>
constexpr match_adaptor(X&& f1, Xs&& ... fs)
: detail::callable_base<F>(BOOST_HOF_FORWARD(X)(f1)), base(BOOST_HOF_FORWARD(Xs)(fs)...)
{}
using F::operator();
using base::operator();
};
template<class F>
struct match_adaptor<F> : detail::callable_base<F>
{
typedef detail::callable_base<F> base;
typedef match_adaptor fit_rewritable_tag;
using F::operator();
BOOST_HOF_INHERIT_CONSTRUCTOR(match_adaptor, detail::callable_base<F>);
};
BOOST_HOF_DECLARE_STATIC_VAR(match, detail::make<match_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,68 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
mutable.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_MUTABLE_H
#define BOOST_HOF_GUARD_FUNCTION_MUTABLE_H
/// mutable
/// =======
///
/// Description
/// -----------
///
/// The `mutable` function adaptor allows using a non-const function object
/// inside of a const-function object. In Fit, all the function adaptors use
/// `const` call overloads, so if there is a function that has a non-const
/// call operator, it couldn't be used directly. So, `mutable_` allows the
/// function to be used inside of the call operator.
///
/// NOTE: This function should be used with caution since many functions are
/// copied, so relying on some internal shared state can be error-prone.
///
/// Synopsis
/// --------
///
/// template<class F>
/// mutable_adaptor<F> mutable_(F f)
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [MutableFunctionObject](MutableFunctionObject)
/// * MoveConstructible
///
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
template<class F>
struct mutable_adaptor
{
mutable F f;
BOOST_HOF_DELEGATE_CONSTRUCTOR(mutable_adaptor, F, f);
BOOST_HOF_RETURNS_CLASS(mutable_adaptor);
template<class... Ts>
BOOST_HOF_SFINAE_RESULT(F, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS(BOOST_HOF_CONST_THIS->f(BOOST_HOF_FORWARD(Ts)(xs)...));
};
BOOST_HOF_DECLARE_STATIC_VAR(mutable_, detail::make<mutable_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,423 @@
/*=============================================================================
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<class... Ts>
/// constexpr auto pack(Ts&&... xs);
///
/// // Capture lvalues by reference and rvalue reference by reference
/// template<class... Ts>
/// constexpr auto pack_forward(Ts&&... xs);
///
/// // Capture lvalues by reference and rvalues by value.
/// template<class... Ts>
/// constexpr auto pack_basic(Ts&&... xs);
///
/// // Join multiple packs together
/// template<class... Ts>
/// 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 <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct sum
/// {
/// template<class T, class U>
/// 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 <boost/hof/detail/seq.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/remove_rvalue_reference.hpp>
#include <boost/hof/detail/unwrap.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/unpack_sequence.hpp>
#include <boost/hof/returns.hpp>
#include <boost/hof/alias.hpp>
#include <boost/hof/decay.hpp>
namespace boost { namespace hof { namespace detail {
template<class...>
struct pack_tag
{};
template<class T, class Tag>
struct pack_holder
: detail::alias_empty<T, Tag>
{};
template<class Seq, class... Ts>
struct pack_base;
template<class T>
struct is_copyable
: std::integral_constant<bool, (
BOOST_HOF_IS_CONSTRUCTIBLE(T, const T&)
)>
{};
template<class T>
struct is_copyable<T&>
: std::true_type
{};
template<class T>
struct is_copyable<T&&>
: std::true_type
{};
template<class T, class Tag, class X, class... Ts, typename std::enable_if<
is_copyable<T>::value && !std::is_lvalue_reference<T>::value
, int>::type = 0>
constexpr T pack_get(X&& x, Ts&&... xs) noexcept(BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(T))
{
return static_cast<T>(boost::hof::alias_value<Tag, T>(BOOST_HOF_FORWARD(X)(x), xs...));
}
template<class T, class Tag, class X, class... Ts, typename std::enable_if<
std::is_lvalue_reference<T>::value
, int>::type = 0>
constexpr T pack_get(X&& x, Ts&&... xs) noexcept
{
return boost::hof::alias_value<Tag, T>(x, xs...);
}
template<class T, class Tag, class X, class... Ts, typename std::enable_if<
!is_copyable<T>::value
, int>::type = 0>
constexpr auto pack_get(X&& x, Ts&&... xs) BOOST_HOF_RETURNS
(
boost::hof::alias_value<Tag, T>(BOOST_HOF_FORWARD(X)(x), xs...)
);
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) || defined(_MSC_VER)
template<class... Ts>
struct pack_holder_base
: Ts::type...
{
template<class... Xs, class=typename std::enable_if<(sizeof...(Xs) == sizeof...(Ts))>::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<typename std::remove_reference<typename Ts::type>::type>::type...)
BOOST_HOF_INHERIT_DEFAULT(pack_holder_base, typename Ts::type...)
#endif
};
template<class T>
struct pack_holder_base<T>
: T::type
{
typedef typename T::type base;
BOOST_HOF_INHERIT_CONSTRUCTOR(pack_holder_base, base);
};
template<class... Ts>
struct pack_holder_builder
{
template<class T, std::size_t N>
struct apply
: pack_holder<T, pack_tag<seq<N>, Ts...>>
{};
};
template<std::size_t... Ns, class... Ts>
struct pack_base<seq<Ns...>, Ts...>
: pack_holder_base<typename pack_holder_builder<Ts...>::template apply<Ts, Ns>...>
{
typedef pack_holder_base<typename pack_holder_builder<Ts...>::template apply<Ts, Ns>...> base;
template<class X1, class X2, class... Xs>
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<class X1, typename std::enable_if<(BOOST_HOF_IS_CONSTRUCTIBLE(base, X1)), int>::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<typename std::remove_reference<Ts>::type>::type...);
BOOST_HOF_INHERIT_DEFAULT(pack_base, Ts...);
BOOST_HOF_RETURNS_CLASS(pack_base);
template<class F>
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(
f(boost::hof::detail::pack_get<Ts, pack_tag<seq<Ns>, Ts...>>(*BOOST_HOF_CONST_THIS, f)...)
);
typedef std::integral_constant<std::size_t, sizeof...(Ts)> fit_function_param_limit;
template<class F>
struct apply
: F::template apply<Ts...>
{};
};
template<class T>
struct pack_base<seq<0>, T>
: pack_holder_base<pack_holder<T, pack_tag<seq<0>, T>>>
{
typedef pack_holder_base<pack_holder<T, pack_tag<seq<0>, T>>> base;
template<class X1, typename std::enable_if<(BOOST_HOF_IS_CONSTRUCTIBLE(base, X1)), int>::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<class F>
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(
f(boost::hof::detail::pack_get<T, pack_tag<seq<0>, T>>(*BOOST_HOF_CONST_THIS, f))
);
typedef std::integral_constant<std::size_t, 1> fit_function_param_limit;
template<class F>
struct apply
: F::template apply<T>
{};
};
#else
template<std::size_t... Ns, class... Ts>
struct pack_base<seq<Ns...>, Ts...>
: pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type...
{
// BOOST_HOF_INHERIT_DEFAULT(pack_base, typename std::remove_cv<typename std::remove_reference<Ts>::type>::type...);
BOOST_HOF_INHERIT_DEFAULT(pack_base, Ts...);
template<class... Xs, BOOST_HOF_ENABLE_IF_CONVERTIBLE_UNPACK(Xs&&, typename pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type)>
constexpr pack_base(Xs&&... xs)
BOOST_HOF_NOEXCEPT(BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(typename pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type, Xs&&)))
: pack_holder<Ts, pack_tag<seq<Ns>, Ts...>>::type(BOOST_HOF_FORWARD(Xs)(xs))...
{}
// typedef pack_base<seq<Ns...>, Ts...> self_t;
BOOST_HOF_RETURNS_CLASS(pack_base);
template<class F>
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(
f(boost::hof::detail::pack_get<Ts, pack_tag<seq<Ns>, Ts...>>(*BOOST_HOF_CONST_THIS, f)...)
);
typedef std::integral_constant<std::size_t, sizeof...(Ts)> fit_function_param_limit;
template<class F>
struct apply
: F::template apply<Ts...>
{};
};
#endif
template<>
struct pack_base<seq<> >
{
template<class F>
constexpr auto operator()(F&& f) const BOOST_HOF_RETURNS
(f());
typedef std::integral_constant<std::size_t, 0> fit_function_param_limit;
template<class F>
struct apply
: F::template apply<>
{};
};
#define BOOST_HOF_DETAIL_UNPACK_PACK_BASE(ref, move) \
template<class F, std::size_t... Ns, class... Ts> \
constexpr auto unpack_pack_base(F&& f, pack_base<seq<Ns...>, Ts...> ref x) \
BOOST_HOF_RETURNS(f(boost::hof::alias_value<pack_tag<seq<Ns>, Ts...>, Ts>(move(x), f)...))
BOOST_HOF_UNARY_PERFECT_FOREACH(BOOST_HOF_DETAIL_UNPACK_PACK_BASE)
template<class P1, class P2>
struct pack_join_base;
// TODO: Extend to join more than two packs at a time
template<std::size_t... Ns1, class... Ts1, std::size_t... Ns2, class... Ts2>
struct pack_join_base<pack_base<seq<Ns1...>, Ts1...>, pack_base<seq<Ns2...>, Ts2...>>
{
static constexpr long total_size = sizeof...(Ts1) + sizeof...(Ts2);
typedef pack_base<typename detail::gens<total_size>::type, Ts1..., Ts2...> result_type;
template<class P1, class P2>
static constexpr result_type call(P1&& p1, P2&& p2)
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(
result_type(
boost::hof::detail::pack_get<Ts1, pack_tag<seq<Ns1>, Ts1...>>(BOOST_HOF_FORWARD(P1)(p1))...,
boost::hof::detail::pack_get<Ts2, pack_tag<seq<Ns2>, Ts2...>>(BOOST_HOF_FORWARD(P2)(p2))...)
)
{
return result_type(
boost::hof::detail::pack_get<Ts1, pack_tag<seq<Ns1>, Ts1...>>(BOOST_HOF_FORWARD(P1)(p1))...,
boost::hof::detail::pack_get<Ts2, pack_tag<seq<Ns2>, Ts2...>>(BOOST_HOF_FORWARD(P2)(p2))...);
}
};
template<class P1, class P2>
struct pack_join_result
: pack_join_base<
typename std::remove_cv<typename std::remove_reference<P1>::type>::type,
typename std::remove_cv<typename std::remove_reference<P2>::type>::type
>
{};
struct pack_basic_f
{
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
pack_base<typename gens<sizeof...(Ts)>::type, typename remove_rvalue_reference<Ts>::type...>(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
struct pack_forward_f
{
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
pack_base<typename gens<sizeof...(Ts)>::type, Ts&&...>(BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
struct pack_f
{
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(
pack_basic_f()(boost::hof::decay(BOOST_HOF_FORWARD(Ts)(xs))...)
);
};
template<class P1, class P2>
constexpr typename pack_join_result<P1, P2>::result_type make_pack_join_dual(P1&& p1, P2&& p2)
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(pack_join_result<P1, P2>::call(BOOST_HOF_FORWARD(P1)(p1), BOOST_HOF_FORWARD(P2)(p2)))
{
return pack_join_result<P1, P2>::call(BOOST_HOF_FORWARD(P1)(p1), BOOST_HOF_FORWARD(P2)(p2));
}
// Manually compute join return type to make older gcc happy
template<class... Ts>
struct join_type;
template<class T>
struct join_type<T>
{
typedef T type;
};
template<class T, class... Ts>
struct join_type<T, Ts...>
{
typedef typename pack_join_result<T, typename join_type<Ts...>::type>::result_type type;
};
template<class P1>
constexpr P1 make_pack_join(P1&& p1) BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(P1, P1&&)
{
return BOOST_HOF_FORWARD(P1)(p1);
}
template<class P1, class... Ps>
constexpr typename join_type<P1, Ps...>::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<class... Ps>
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<class T, class... Ts>
struct unpack_sequence<detail::pack_base<T, Ts...>>
{
template<class F, class P>
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

View File

@@ -0,0 +1,292 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
partial.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_PARTIAL_H
#define BOOST_HOF_GUARD_FUNCTION_PARTIAL_H
/// partial
/// ========
///
/// Description
/// -----------
///
/// The `partial` function adaptor allows partial application of the function.
/// If the function can not be called with all the parameters, it will return
/// another function. It will repeatedly do this until the function can
/// finally be called. By default, `partial` captures all of its variables by
/// value, just like bind. As such all parameters must be `MoveConstructible`
/// when the function is aprtial application. `std::ref` can be used to
/// capture references instead.
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr partial_adaptor<F> partial(F f);
///
/// Semantics
/// ---------
///
/// assert(partial(f)(xs...)(ys...) == f(xs..., ys...));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct sum
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// assert(3 == partial(sum())(1)(2));
/// }
///
/// References
/// ----------
///
/// * [Partial application](https://en.wikipedia.org/wiki/Partial_application)
/// * [Currying](https://en.wikipedia.org/wiki/Currying)
///
#include <boost/hof/first_of.hpp>
#include <boost/hof/static.hpp>
#include <boost/hof/pipable.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
// TODO: Get rid of sequence parameter
// Forward declare partial_adaptor, since it will be used below
template<class F, class Pack=void >
struct partial_adaptor;
BOOST_HOF_DECLARE_STATIC_VAR(partial, detail::make<partial_adaptor>);
namespace detail {
template<class Derived, class F, class Pack>
struct partial_adaptor_invoke
{
template<class... Ts>
constexpr const F& get_function(Ts&&...) const noexcept
{
return static_cast<const F&>(static_cast<const Derived&>(*this));
}
template<class... Ts>
constexpr const Pack& get_pack(Ts&&...) const noexcept
{
return static_cast<const Pack&>(static_cast<const Derived&>(*this));
}
BOOST_HOF_RETURNS_CLASS(partial_adaptor_invoke);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT
(
typename result_of<decltype(boost::hof::pack_join),
id_<const Pack&>,
result_of<decltype(boost::hof::pack_forward), id_<Ts>...>
>::type,
id_<F&&>
)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
boost::hof::pack_join
(
BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(xs...)),
boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)
)
(BOOST_HOF_RETURNS_C_CAST(F&&)(BOOST_HOF_CONST_THIS->get_function(xs...)))
);
};
#ifdef _MSC_VER
#define BOOST_HOF_PARTIAL_RETURNS(...) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); }
#else
#define BOOST_HOF_PARTIAL_RETURNS BOOST_HOF_SFINAE_RETURNS
#endif
template<class Derived, class F, class Pack>
struct partial_adaptor_join
{
template<class... Ts>
constexpr const F& get_function(Ts&&...) const noexcept
{
return static_cast<const F&>(static_cast<const Derived&>(*this));
}
template<class... Ts>
constexpr const Pack& get_pack(Ts&&...) const noexcept
{
return static_cast<const Pack&>(static_cast<const Derived&>(*this));
}
BOOST_HOF_RETURNS_CLASS(partial_adaptor_join);
template<class... Ts, class=typename std::enable_if<
((sizeof...(Ts) + Pack::fit_function_param_limit::value) < function_param_limit<F>::value)
>::type>
constexpr auto operator()(Ts&&... xs) const
#ifdef _MSC_VER
// Workaround ICE on MSVC
noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F, F&&) && noexcept(boost::hof::pack_join(std::declval<const Pack&>(), boost::hof::pack(BOOST_HOF_FORWARD(Ts)(xs)...))))
#endif
BOOST_HOF_PARTIAL_RETURNS
(
boost::hof::partial
(
BOOST_HOF_RETURNS_C_CAST(F&&)(BOOST_HOF_CONST_THIS->get_function(xs...)),
boost::hof::pack_join(BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(xs...)), boost::hof::pack(BOOST_HOF_FORWARD(Ts)(xs)...))
)
);
};
template<class Derived, class F>
struct partial_adaptor_pack
{
constexpr partial_adaptor_pack() noexcept
{}
template<class... Ts>
constexpr const F& get_function(Ts&&...) const noexcept
{
return static_cast<const F&>(static_cast<const Derived&>(*this));
}
BOOST_HOF_RETURNS_CLASS(partial_adaptor_pack);
template<class... Ts, class=typename std::enable_if<
(sizeof...(Ts) < function_param_limit<F>::value)
>::type>
constexpr auto operator()(Ts&&... xs) const
#ifdef _MSC_VER
// Workaround ICE on MSVC
noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F, F&&) && noexcept(boost::hof::pack(BOOST_HOF_FORWARD(Ts)(xs)...)))
#endif
BOOST_HOF_PARTIAL_RETURNS
(
boost::hof::partial
(
BOOST_HOF_RETURNS_C_CAST(F&&)(BOOST_HOF_CONST_THIS->get_function(xs...)),
boost::hof::pack(BOOST_HOF_FORWARD(Ts)(xs)...)
)
);
};
template<class F, class Pack>
struct partial_adaptor_base
{
typedef basic_first_of_adaptor
<
partial_adaptor_invoke<partial_adaptor<F, Pack>, F, Pack>,
partial_adaptor_join<partial_adaptor<F, Pack>, F, Pack>
> type;
};
template<class Derived, class F>
struct partial_adaptor_pack_base
{
typedef basic_first_of_adaptor
<
F,
partial_adaptor_pack<Derived, F>
> type;
};
}
template<class F, class Pack>
struct partial_adaptor : detail::partial_adaptor_base<F, Pack>::type, F, Pack
{
typedef typename detail::partial_adaptor_base<F, Pack>::type base;
typedef partial_adaptor fit_rewritable1_tag;
template<class... Ts>
constexpr const F& base_function(Ts&&...) const noexcept
{
return *this;
}
constexpr const Pack& get_pack() const noexcept
{
return *this;
}
using base::operator();
BOOST_HOF_INHERIT_DEFAULT(partial_adaptor, base, F, Pack);
template<class X, class S>
constexpr partial_adaptor(X&& x, S&& seq)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(Pack, S&&))
: F(BOOST_HOF_FORWARD(X)(x)), Pack(BOOST_HOF_FORWARD(S)(seq))
{}
};
template<class F>
struct partial_adaptor<F, void> : detail::partial_adaptor_pack_base<partial_adaptor<F, void>, detail::callable_base<F>>::type
{
typedef typename detail::partial_adaptor_pack_base<partial_adaptor<F, void>, detail::callable_base<F>>::type base;
typedef partial_adaptor fit_rewritable1_tag;
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&...) const noexcept
{
return *this;
}
using base::operator();
BOOST_HOF_INHERIT_CONSTRUCTOR(partial_adaptor, base);
};
// Make partial_adaptor work with pipable_adaptor by removing its pipableness
template<class F>
struct partial_adaptor<pipable_adaptor<F>, void>
: partial_adaptor<F, void>
{
typedef partial_adaptor<F, void> base;
typedef partial_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(partial_adaptor, base);
};
template<class F>
struct partial_adaptor<static_<pipable_adaptor<F>>, void>
: partial_adaptor<F, void>
{
typedef partial_adaptor<F, void> base;
typedef partial_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(partial_adaptor, base);
};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,215 @@
/*=============================================================================
Copyright (c) 2012 Paul Fultz II
pipable.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_PIPABLE_H
#define BOOST_HOF_GUARD_FUNCTION_PIPABLE_H
/// pipable
/// =======
///
/// Description
/// -----------
///
/// The `pipable` function adaptor provides an extension method. The first
/// parameter of the function can be piped into the function using the pipe
/// `|` operator. This can be especially convenient when there are a lot of
/// nested function calls. Functions that are made pipable can still be called
/// the traditional way without piping in the first parameter.
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr pipable_adaptor<F> pipable(F f);
///
/// Semantics
/// ---------
///
/// assert(x | pipable(f)(ys...) == f(x, ys...));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct sum
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// assert(3 == (1 | pipable(sum())(2)));
/// assert(3 == pipable(sum())(1, 2));
/// }
///
/// References
/// ----------
///
/// * [Extension methods](<Extension methods>)
///
#include <boost/hof/first_of.hpp>
#include <boost/hof/pack.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/limit.hpp>
namespace boost { namespace hof {
template<class F>
struct pipable_adaptor;
namespace detail {
template<class F, class Pack>
struct pipe_closure : F, Pack
{
template<class X, class P>
constexpr pipe_closure(X&& fp, P&& packp)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(Pack, P&&))
: F(BOOST_HOF_FORWARD(X)(fp)), Pack(BOOST_HOF_FORWARD(P)(packp))
{}
template<class... Ts>
constexpr const F& base_function(Ts&&...) const noexcept
{
return *this;
}
template<class... Ts>
constexpr const Pack& get_pack(Ts&&...) const noexcept
{
return *this;
}
template<class A>
struct invoke
{
A a;
const pipe_closure * self;
template<class X>
constexpr invoke(X&& xp, const pipe_closure * selfp)
BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(A, X&&))
: a(BOOST_HOF_FORWARD(X)(xp)), self(selfp)
{}
BOOST_HOF_RETURNS_CLASS(invoke);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const F&, id_<A>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(BOOST_HOF_RETURNS_STATIC_CAST(const F&)(*BOOST_HOF_CONST_THIS->self)(BOOST_HOF_FORWARD(A)(a), BOOST_HOF_FORWARD(Ts)(xs)...));
};
BOOST_HOF_RETURNS_CLASS(pipe_closure);
template<class A>
constexpr BOOST_HOF_SFINAE_RESULT(const Pack&, id_<invoke<A&&>>)
operator()(A&& a) const BOOST_HOF_SFINAE_RETURNS
(BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(a))(invoke<A&&>(BOOST_HOF_FORWARD(A)(a), BOOST_HOF_CONST_THIS)));
};
template<class F, class Pack>
constexpr auto make_pipe_closure(F f, Pack&& p) BOOST_HOF_RETURNS
(
pipe_closure<F, typename std::remove_reference<Pack>::type>(BOOST_HOF_RETURNS_STATIC_CAST(F&&)(f), BOOST_HOF_FORWARD(Pack)(p))
);
template<class Derived, class F>
struct pipe_pack
{
template<class... Ts>
constexpr const F& get_function(Ts&&...) const noexcept
{
return static_cast<const F&>(static_cast<const Derived&>(*this));
}
BOOST_HOF_RETURNS_CLASS(pipe_pack);
template<class... Ts, class=typename std::enable_if<
(sizeof...(Ts) < function_param_limit<F>::value)
>::type>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
(make_pipe_closure(BOOST_HOF_RETURNS_C_CAST(F&&)(BOOST_HOF_CONST_THIS->get_function(xs...)), boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)));
};
template<class A, class F, class Pack>
constexpr auto operator|(A&& a, const pipe_closure<F, Pack>& p) BOOST_HOF_RETURNS
(p(BOOST_HOF_FORWARD(A)(a)));
}
template<class F>
struct pipable_adaptor
: detail::basic_first_of_adaptor<detail::callable_base<F>, detail::pipe_pack<pipable_adaptor<F>, detail::callable_base<F>> >
{
typedef detail::basic_first_of_adaptor<detail::callable_base<F>, detail::pipe_pack<pipable_adaptor<F>, detail::callable_base<F>> > base;
typedef pipable_adaptor fit_rewritable_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(pipable_adaptor, base);
constexpr const detail::callable_base<F>& base_function() const noexcept
{
return *this;
}
};
template<class A, class F>
constexpr auto operator|(A&& a, const pipable_adaptor<F>& p) BOOST_HOF_RETURNS
(p(BOOST_HOF_FORWARD(A)(a)));
BOOST_HOF_DECLARE_STATIC_VAR(pipable, detail::make<pipable_adaptor>);
namespace detail {
template<class F>
struct static_function_wrapper;
// Operators for static_function_wrapper adaptor
template<class A, class F>
auto operator|(A&& a, const boost::hof::detail::static_function_wrapper<F>& f) BOOST_HOF_RETURNS
(f(BOOST_HOF_FORWARD(A)(a)));
template<class F>
struct static_default_function;
// Operators for static_default_function adaptor
template<class A, class F>
auto operator|(A&& a, const boost::hof::detail::static_default_function<F>& f) BOOST_HOF_RETURNS
(f(BOOST_HOF_FORWARD(A)(a)));
}
template<class F>
struct static_;
// Operators for static_ adaptor
template<class A, class F>
auto operator|(A&& a, static_<F> f) BOOST_HOF_RETURNS
(f.base_function().base_function()(BOOST_HOF_FORWARD(A)(a)));
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,468 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
placeholders.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_PLACEHOLDERS_H
#define BOOST_HOF_GUARD_FUNCTION_PLACEHOLDERS_H
/// placeholders
/// ============
///
/// Description
/// -----------
///
/// The placeholders provide `std::bind` compatible placeholders that
/// additionally provide basic C++ operators that creates bind expressions.
/// Each bind expression supports `constexpr` function evaluation.
///
/// Synopsis
/// --------
///
/// namespace placeholders {
/// placeholder<1> _1 = {};
/// placeholder<2> _2 = {};
/// placeholder<3> _3 = {};
/// placeholder<4> _4 = {};
/// placeholder<5> _5 = {};
/// placeholder<6> _6 = {};
/// placeholder<7> _7 = {};
/// placeholder<8> _8 = {};
/// placeholder<9> _9 = {};
/// }
///
/// Operators
/// ---------
///
/// * Binary operators: +,-,*,/,%,>>,<<,>,<,<=,>=,==,!=,&,^,|,&&,||
/// * Assign operators: +=,-=,*=,/=,%=,>>=,<<=,&=,|=,^=
/// * Unary operators: !,~,+,-,*,++,--
///
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// int main() {
/// auto sum = _1 + _2;
/// assert(3 == sum(1, 2));
/// }
///
///
/// unamed placeholder
/// ==================
///
/// Description
/// -----------
///
/// The unamed placeholder can be used to build simple functions from C++
/// operators.
///
/// Note: The function produced by the unamed placeholder is not a bind expression.
///
/// Synopsis
/// --------
///
/// namespace placeholders {
/// /* unspecified */ _ = {};
/// }
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// int main() {
/// auto sum = _ + _;
/// assert(3 == sum(1, 2));
/// }
///
#include <boost/hof/returns.hpp>
#include <boost/hof/lazy.hpp>
#include <boost/hof/protect.hpp>
#if defined(_MSC_VER) && _MSC_VER >= 1910
#include <boost/hof/detail/pp.hpp>
#endif
namespace boost { namespace hof { namespace detail {
template<int N>
struct simple_placeholder
{};
}}} // namespace boost::hof
namespace std {
template<int N>
struct is_placeholder<boost::hof::detail::simple_placeholder<N>>
: std::integral_constant<int, N>
{};
}
namespace boost { namespace hof {
#define BOOST_HOF_FOREACH_BINARY_OP(m) \
m(+, add) \
m(-, subtract) \
m(*, multiply) \
m(/, divide) \
m(%, remainder) \
m(>>, shift_right) \
m(<<, shift_left) \
m(>, greater_than) \
m(<, less_than) \
m(<=, less_than_equal) \
m(>=, greater_than_equal) \
m(==, equal) \
m(!=, not_equal) \
m(&, bit_and) \
m(^, xor_) \
m(|, bit_or) \
m(&&, and_) \
m(||, or_)
#define BOOST_HOF_FOREACH_ASSIGN_OP(m) \
m(+=, assign_add) \
m(-=, assign_subtract) \
m(*=, assign_multiply) \
m(/=, assign_divide) \
m(%=, assign_remainder) \
m(>>=, assign_right_shift) \
m(<<=, assign_left_shift) \
m(&=, assign_bit_and) \
m(|=, assign_bit_or) \
m(^=, assign_xor)
#ifndef _MSC_VER
#define BOOST_HOF_FOREACH_UNARY_OP(m) \
m(!, not_) \
m(~, compl_) \
m(+, unary_plus) \
m(-, unary_subtract) \
m(*, dereference) \
m(++, increment) \
m(--, decrement)
#else
#define BOOST_HOF_FOREACH_UNARY_OP(m) \
m(!, not_) \
m(~, compl_) \
m(+, unary_plus) \
m(-, unary_subtract) \
m(*, dereference)
#endif
namespace operators {
struct call
{
template<class F, class... Ts>
constexpr auto operator()(F&& f, Ts&&... xs) const BOOST_HOF_RETURNS
(f(BOOST_HOF_FORWARD(Ts)(xs)...));
};
// MSVC 2017 ICEs on && and || in conxtexpr, so we fallback on bitwise operators
#if defined(_MSC_VER) && _MSC_VER >= 1910
#define BOOST_HOF_BINARY_OP_SKIP_and_ ()
#define BOOST_HOF_BINARY_OP_SKIP_or_ ()
struct and_
{
template<class T, class U>
constexpr auto operator()(T&& x, U&& y) const
noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y)))
-> decltype(BOOST_HOF_FORWARD(T)(x) && BOOST_HOF_FORWARD(U)(y))
{ return BOOST_HOF_FORWARD(T)(x) & BOOST_HOF_FORWARD(U)(y); }
};
struct or_
{
template<class T, class U>
constexpr auto operator()(T&& x, U&& y) const
noexcept(noexcept(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y)))
-> decltype(BOOST_HOF_FORWARD(T)(x) || BOOST_HOF_FORWARD(U)(y))
{ return BOOST_HOF_FORWARD(T)(x) | BOOST_HOF_FORWARD(U)(y); }
};
#define BOOST_HOF_BINARY_OP_IMPL(op, name) \
struct name \
{ \
template<class T, class U> \
BOOST_HOF_USING(ex_failure, decltype(std::declval<T>() op std::declval<U>())); \
struct failure : as_failure<ex_failure> {}; \
template<class T, class U> \
constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
(BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
};
#define BOOST_HOF_BINARY_OP(op, name) \
BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_PP_CAT(BOOST_HOF_BINARY_OP_SKIP_, name))) \
(BOOST_HOF_PP_EMPTY, BOOST_HOF_BINARY_OP_IMPL)(op, name)
#else
#define BOOST_HOF_BINARY_OP(op, name) \
struct name \
{ \
template<class T, class U> \
constexpr auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS \
(BOOST_HOF_FORWARD(T)(x) op BOOST_HOF_FORWARD(U)(y)); \
};
#endif
BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_BINARY_OP)
BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_BINARY_OP)
#define BOOST_HOF_UNARY_OP(op, name) \
struct name \
{ \
template<class T> \
constexpr auto operator()(T&& x) const BOOST_HOF_RETURNS \
(op(BOOST_HOF_FORWARD(T)(x))); \
};
BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNARY_OP)
}
template<int N>
struct placeholder
{
#if BOOST_HOF_HAS_MANGLE_OVERLOAD
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
( boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...) );
#else
template<class... Ts>
struct result_call
{ typedef decltype(boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), std::declval<Ts>()...)) type; };
template<class... Ts>
constexpr typename result_call<Ts...>::type operator()(Ts&&... xs) const
{ return boost::hof::lazy(operators::call())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(Ts)(xs)...); };
#endif
#define BOOST_HOF_PLACEHOLDER_UNARY_OP(op, name) \
constexpr auto operator op () const BOOST_HOF_RETURNS \
( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>()) );
BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_PLACEHOLDER_UNARY_OP)
#define BOOST_HOF_PLACEHOLDER_ASSIGN_OP(op, name) \
template<class T> \
constexpr auto operator op (T&& x) const BOOST_HOF_RETURNS \
( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) );
BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_PLACEHOLDER_ASSIGN_OP)
};
#if BOOST_HOF_HAS_MANGLE_OVERLOAD
#define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
template<class T, int N> \
constexpr inline auto operator op (const placeholder<N>&, T&& x) BOOST_HOF_RETURNS \
( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)) ); \
template<class T, int N> \
constexpr inline auto operator op (T&& x, const placeholder<N>&) BOOST_HOF_RETURNS \
( boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()) ); \
template<int N, int M> \
constexpr inline auto operator op (const placeholder<N>&, const placeholder<M>&) BOOST_HOF_RETURNS \
( boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()) );
#else
#define BOOST_HOF_PLACEHOLDER_BINARY_OP(op, name) \
template<class T, class U> \
struct result_ ## name \
{ typedef decltype(boost::hof::lazy(operators::name())(std::declval<T>(), std::declval<U>())) type; }; \
template<class T, int N> \
constexpr inline typename result_ ## name<detail::simple_placeholder<N>, T>::type operator op (const placeholder<N>&, T&& x) \
{ return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), BOOST_HOF_FORWARD(T)(x)); } \
template<class T, int N> \
constexpr inline typename result_ ## name<T, detail::simple_placeholder<N>>::type operator op (T&& x, const placeholder<N>&) \
{ return boost::hof::lazy(operators::name())(BOOST_HOF_FORWARD(T)(x), detail::simple_placeholder<N>()); } \
template<int N, int M> \
constexpr inline typename result_ ## name<detail::simple_placeholder<N>, detail::simple_placeholder<M>>::type operator op (const placeholder<N>&, const placeholder<M>&) \
{ return boost::hof::lazy(operators::name())(detail::simple_placeholder<N>(), detail::simple_placeholder<M>()); }
#endif
BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_PLACEHOLDER_BINARY_OP)
namespace placeholders {
BOOST_HOF_DECLARE_STATIC_VAR(_1, placeholder<1>);
BOOST_HOF_DECLARE_STATIC_VAR(_2, placeholder<2>);
BOOST_HOF_DECLARE_STATIC_VAR(_3, placeholder<3>);
BOOST_HOF_DECLARE_STATIC_VAR(_4, placeholder<4>);
BOOST_HOF_DECLARE_STATIC_VAR(_5, placeholder<5>);
BOOST_HOF_DECLARE_STATIC_VAR(_6, placeholder<6>);
BOOST_HOF_DECLARE_STATIC_VAR(_7, placeholder<7>);
BOOST_HOF_DECLARE_STATIC_VAR(_8, placeholder<8>);
BOOST_HOF_DECLARE_STATIC_VAR(_9, placeholder<9>);
}
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;
using placeholders::_4;
using placeholders::_5;
using placeholders::_6;
using placeholders::_7;
using placeholders::_8;
using placeholders::_9;
namespace detail {
struct unamed_placeholder
{
template<class T, class Invoker>
struct partial_ap
{
T val;
BOOST_HOF_INHERIT_DEFAULT_EMPTY(partial_ap, T)
template<class X, class... Xs, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, X&&, Xs&&...)>
constexpr partial_ap(X&& x, Xs&&... xs) : val(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(Xs)(xs)...)
{}
BOOST_HOF_RETURNS_CLASS(partial_ap);
struct partial_ap_failure
{
template<class Failure>
struct apply
{
template<class... Xs>
struct of;
template<class X>
struct of<X>
: Failure::template of<typename std::add_const<T>::type, X>
{};
};
};
struct failure
: failure_map<partial_ap_failure, Invoker>
{};
template<class X>
constexpr BOOST_HOF_SFINAE_RESULT(const Invoker&, id_<T>, id_<X>)
operator()(X&& x) const BOOST_HOF_SFINAE_RETURNS
(
Invoker()(BOOST_HOF_CONST_THIS->val, BOOST_HOF_FORWARD(X)(x))
);
};
template<class Invoker, class T>
static constexpr partial_ap<T, Invoker> make_partial_ap(T&& x)
{
return {BOOST_HOF_FORWARD(T)(x)};
}
template<class Op>
struct left
{
struct failure
: failure_for<Op>
{};
template<class T, class X>
constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<T>, id_<X>)
operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
(Op()(BOOST_HOF_FORWARD(T)(val), BOOST_HOF_FORWARD(X)(x)));
};
template<class Op>
struct right
{
struct right_failure
{
template<class Failure>
struct apply
{
template<class T, class U, class... Ts>
struct of
: Failure::template of<U, T, Ts...>
{};
};
};
struct failure
: failure_map<right_failure, Op>
{};
template<class T, class X>
constexpr BOOST_HOF_SFINAE_RESULT(const Op&, id_<X>, id_<T>)
operator()(T&& val, X&& x) const BOOST_HOF_SFINAE_RETURNS
(Op()(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(T)(val)));
};
#define BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP(op, name) \
constexpr auto operator op () const BOOST_HOF_RETURNS \
( operators::name() );
BOOST_HOF_FOREACH_UNARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_UNARY_OP)
#define BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP(op, name) \
template<class T> \
constexpr auto operator op (const T& x) const BOOST_HOF_RETURNS \
( partial_ap<T, left<operators::name>>(x) );
BOOST_HOF_FOREACH_ASSIGN_OP(BOOST_HOF_UNAMED_PLACEHOLDER_ASSIGN_OP)
};
#define BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP(op, name) \
template<class T> \
constexpr inline auto operator op (const unamed_placeholder&, const T& x) BOOST_HOF_RETURNS \
( unamed_placeholder::make_partial_ap<unamed_placeholder::right<operators::name>>(boost::hof::decay(x)) ); \
template<class T> \
constexpr inline auto operator op (const T& x, const unamed_placeholder&) BOOST_HOF_RETURNS \
( unamed_placeholder::make_partial_ap<unamed_placeholder::left<operators::name>>(boost::hof::decay(x)) ); \
constexpr inline auto operator op (const unamed_placeholder&, const unamed_placeholder&) BOOST_HOF_RETURNS \
( operators::name() );
BOOST_HOF_FOREACH_BINARY_OP(BOOST_HOF_UNAMED_PLACEHOLDER_BINARY_OP)
}
namespace placeholders {
BOOST_HOF_DECLARE_STATIC_VAR(_, detail::unamed_placeholder);
}
using placeholders::_;
}} // namespace boost::hof
namespace std {
template<int N>
struct is_placeholder<boost::hof::placeholder<N>>
: std::integral_constant<int, N>
{};
}
namespace boost {
template<class T>
struct is_placeholder;
template<int N>
struct is_placeholder<boost::hof::placeholder<N>>
: std::integral_constant<int, N>
{};
}
#endif

View File

@@ -0,0 +1,265 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
proj.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_ON_H
#define BOOST_HOF_GUARD_FUNCTION_ON_H
/// proj
/// ====
///
/// Description
/// -----------
///
/// The `proj` function adaptor applies a projection onto the parameters of
/// another function. This is useful, for example, to define a function for
/// sorting such that the ordering is based off of the value of one of its
/// member fields.
///
/// Also, if just a projection is given, then the projection will be called
/// for each of its arguments.
///
/// Note: All projections are always evaluated in order from left-to-right.
///
/// Synopsis
/// --------
///
/// template<class Projection, class F>
/// constexpr proj_adaptor<Projection, F> proj(Projection p, F f);
///
/// template<class Projection>
/// constexpr proj_adaptor<Projection> proj(Projection p);
///
/// Semantics
/// ---------
///
/// assert(proj(p, f)(xs...) == f(p(xs)...));
/// assert(proj(p)(xs...) == p(xs)...);
///
/// Requirements
/// ------------
///
/// Projection must be:
///
/// * [UnaryInvocable](UnaryInvocable)
/// * MoveConstructible
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct foo
/// {
/// foo(int x_) : x(x_)
/// {}
/// int x;
/// };
///
/// int main() {
/// assert(boost::hof::proj(&foo::x, _ + _)(foo(1), foo(2)) == 3);
/// }
///
/// References
/// ----------
///
/// * [Projections](Projections)
/// * [Variadic print](<Variadic print>)
///
#include <utility>
#include <boost/hof/always.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/detail/result_type.hpp>
#include <boost/hof/apply_eval.hpp>
namespace boost { namespace hof {
namespace detail {
template<class T, class Projection>
struct project_eval
{
T&& x;
const Projection& p;
template<class X, class P>
constexpr project_eval(X&& xp, const P& pp) : x(BOOST_HOF_FORWARD(X)(xp)), p(pp)
{}
constexpr auto operator()() const BOOST_HOF_RETURNS
(p(BOOST_HOF_FORWARD(T)(x)));
};
template<class T, class Projection>
constexpr project_eval<T, Projection> make_project_eval(T&& x, const Projection& p)
{
return project_eval<T, Projection>(BOOST_HOF_FORWARD(T)(x), p);
}
template<class T, class Projection>
struct project_void_eval
{
T&& x;
const Projection& p;
template<class X, class P>
constexpr project_void_eval(X&& xp, const P& pp) : x(BOOST_HOF_FORWARD(X)(xp)), p(pp)
{}
struct void_ {};
constexpr void_ operator()() const
{
return p(BOOST_HOF_FORWARD(T)(x)), void_();
}
};
template<class T, class Projection>
constexpr project_void_eval<T, Projection> make_project_void_eval(T&& x, const Projection& p)
{
return project_void_eval<T, Projection>(BOOST_HOF_FORWARD(T)(x), p);
}
template<class Projection, class F, class... Ts,
class R=decltype(
std::declval<const F&>()(std::declval<const Projection&>()(std::declval<Ts>())...)
)>
constexpr R by_eval(const Projection& p, const F& f, Ts&&... xs)
{
return boost::hof::apply_eval(f, make_project_eval(BOOST_HOF_FORWARD(Ts)(xs), p)...);
}
#if BOOST_HOF_NO_ORDERED_BRACE_INIT
#define BOOST_HOF_BY_VOID_RETURN BOOST_HOF_ALWAYS_VOID_RETURN
#else
#if BOOST_HOF_NO_CONSTEXPR_VOID
#define BOOST_HOF_BY_VOID_RETURN boost::hof::detail::swallow
#else
#define BOOST_HOF_BY_VOID_RETURN void
#endif
#endif
template<class Projection, class... Ts>
constexpr BOOST_HOF_ALWAYS_VOID_RETURN by_void_eval(const Projection& p, Ts&&... xs)
{
return boost::hof::apply_eval(boost::hof::always(), boost::hof::detail::make_project_void_eval(BOOST_HOF_FORWARD(Ts)(xs), p)...);
}
struct swallow
{
template<class... Ts>
constexpr swallow(Ts&&...)
{}
};
}
template<class Projection, class F=void>
struct proj_adaptor;
template<class Projection, class F>
struct proj_adaptor : detail::compressed_pair<detail::callable_base<Projection>, detail::callable_base<F>>, detail::function_result_type<F>
{
typedef proj_adaptor fit_rewritable_tag;
typedef detail::compressed_pair<detail::callable_base<Projection>, detail::callable_base<F>> base;
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return this->second(xs...);;
}
template<class... Ts>
constexpr const detail::callable_base<Projection>& base_projection(Ts&&... xs) const
{
return this->first(xs...);
}
struct by_failure
{
template<class Failure>
struct apply
{
template<class... Ts>
struct of
: Failure::template of<decltype(std::declval<detail::callable_base<Projection>>()(std::declval<Ts>()))...>
{};
};
};
struct failure
: failure_map<by_failure, detail::callable_base<F>>
{};
BOOST_HOF_INHERIT_CONSTRUCTOR(proj_adaptor, base)
BOOST_HOF_RETURNS_CLASS(proj_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F>&, result_of<const detail::callable_base<Projection>&, id_<Ts>>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
boost::hof::detail::by_eval(
BOOST_HOF_MANGLE_CAST(const detail::callable_base<Projection>&)(BOOST_HOF_CONST_THIS->base_projection(xs...)),
BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
BOOST_HOF_FORWARD(Ts)(xs)...
)
);
};
template<class Projection>
struct proj_adaptor<Projection, void> : detail::callable_base<Projection>
{
typedef proj_adaptor fit_rewritable1_tag;
template<class... Ts>
constexpr const detail::callable_base<Projection>& base_projection(Ts&&... xs) const
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_INHERIT_DEFAULT(proj_adaptor, detail::callable_base<Projection>)
template<class P, BOOST_HOF_ENABLE_IF_CONVERTIBLE(P, detail::callable_base<Projection>)>
constexpr proj_adaptor(P&& p)
: detail::callable_base<Projection>(BOOST_HOF_FORWARD(P)(p))
{}
BOOST_HOF_RETURNS_CLASS(proj_adaptor);
template<class... Ts, class=detail::holder<decltype(std::declval<Projection>()(std::declval<Ts>()))...>>
constexpr BOOST_HOF_BY_VOID_RETURN operator()(Ts&&... xs) const
{
#if BOOST_HOF_NO_ORDERED_BRACE_INIT
return boost::hof::detail::by_void_eval(this->base_projection(xs...), BOOST_HOF_FORWARD(Ts)(xs)...);
#else
#if BOOST_HOF_NO_CONSTEXPR_VOID
return
#endif
boost::hof::detail::swallow{
(this->base_projection(xs...)(BOOST_HOF_FORWARD(Ts)(xs)), 0)...
};
#endif
}
};
BOOST_HOF_DECLARE_STATIC_VAR(proj, detail::make<proj_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,80 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
protect.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_PROTECT_H
#define BOOST_HOF_GUARD_FUNCTION_PROTECT_H
/// protect
/// =======
///
/// Description
/// -----------
///
/// The `protect` function adaptor can be used to make a bind expression be
/// treated as a normal function instead. Both `bind` and
/// [`lazy`](/include/boost/hof/lazy) eargerly evaluates nested bind expressions.
/// The `protect` adaptor masks the type so `bind` or
/// [`lazy`](/include/boost/hof/lazy) no longer recognizes the function as bind
/// expression and evaluates it.
///
/// Synopsis
/// --------
///
/// template<class F>
/// constexpr protect_adaptor<F> protect(F f);
///
/// Semantics
/// ---------
///
/// assert(lazy(f)(protect(lazy(g)(_1)))() == f(lazy(g)(_1)))
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// int main() {
/// auto lazy_id = lazy(identity)(_1);
/// auto lazy_apply = lazy(apply)(protect(lazy_id), _1);
/// assert(lazy_apply(3) == 3);
/// }
///
/// See Also
/// --------
///
/// * [lazy](lazy)
///
#include <utility>
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
template<class F>
struct protect_adaptor : detail::callable_base<F>
{
typedef protect_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(protect_adaptor, detail::callable_base<F>)
};
BOOST_HOF_DECLARE_STATIC_VAR(protect, detail::make<protect_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,162 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
repeat.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_REPEAT_H
#define BOOST_HOF_GUARD_REPEAT_H
/// repeat
/// ======
///
/// Description
/// -----------
///
/// The `repeat` function decorator will repeatedly apply a function a given
/// number of times.
///
///
/// Synopsis
/// --------
///
/// template<class Integral>
/// constexpr auto repeat(Integral);
///
/// Semantics
/// ---------
///
/// assert(repeat(std::integral_constant<int, 0>{})(f)(xs...) == f(xs...));
/// assert(repeat(std::integral_constant<int, 1>{})(f)(xs...) == f(f(xs...)));
/// assert(repeat(0)(f)(xs...) == f(xs...));
/// assert(repeat(1)(f)(xs...) == f(f(xs...)));
///
/// Requirements
/// ------------
///
/// Integral must be:
///
/// * Integral
///
/// Or:
///
/// * IntegralConstant
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct increment
/// {
/// template<class T>
/// constexpr T operator()(T x) const
/// {
/// return x + 1;
/// }
/// };
///
/// int main() {
/// auto increment_by_5 = boost::hof::repeat(std::integral_constant<int, 5>())(increment());
/// assert(increment_by_5(1) == 6);
/// }
///
#include <boost/hof/always.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/decorate.hpp>
#include <boost/hof/first_of.hpp>
#include <boost/hof/detail/recursive_constexpr_depth.hpp>
namespace boost { namespace hof { namespace detail {
template<int N>
struct repeater
{
template<class F, class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(repeater<N-1>, id_<const F&>, result_of<const F&, id_<Ts>...>)
operator()(const F& f, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
repeater<N-1>()(f, f(BOOST_HOF_FORWARD(Ts)(xs)...))
);
};
template<>
struct repeater<0>
{
template<class F, class T>
constexpr T operator()(const F&, T&& x) const
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(T(x))
{
return x;
}
};
struct repeat_constant_decorator
{
template<class Integral, class F, class... Ts>
constexpr auto operator()(Integral, const F& f, Ts&&... xs) const BOOST_HOF_RETURNS
(
detail::repeater<Integral::type::value>()
(
f,
BOOST_HOF_FORWARD(Ts)(xs)...
)
);
};
template<int Depth>
struct repeat_integral_decorator
{
template<class Integral, class F, class T, class... Ts, class Self=repeat_integral_decorator<Depth-1>>
constexpr auto operator()(Integral n, const F& f, T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
(
(n) ?
Self()(n-1, f, f(BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)) :
BOOST_HOF_FORWARD(T)(x)
);
};
template<>
struct repeat_integral_decorator<0>
{
template<class Integral, class F, class T, class Self=repeat_integral_decorator<0>>
#if BOOST_HOF_HAS_RELAXED_CONSTEXPR
constexpr
#endif
auto operator()(Integral n, const F& f, T x) const
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((n--, f(BOOST_HOF_FORWARD(T)(x))))
-> decltype(f(BOOST_HOF_FORWARD(T)(x)))
{
while(n > 0)
{
n--;
x = f(BOOST_HOF_FORWARD(T)(x));
}
return x;
}
// TODO: Add overload for lvalue
};
}
#if BOOST_HOF_HAS_RELAXED_CONSTEXPR
#define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH 1
#else
#define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH
#endif
BOOST_HOF_DECLARE_STATIC_VAR(repeat, decorate_adaptor<
boost::hof::first_of_adaptor<
detail::repeat_constant_decorator,
detail::repeat_integral_decorator<BOOST_HOF_REPEAT_CONSTEXPR_DEPTH>
>>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,181 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
repeat_while.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_REPEAT_WHILE_H
#define BOOST_HOF_GUARD_REPEAT_WHILE_H
/// repeat_while
/// ======
///
/// Description
/// -----------
///
/// The `repeat_while` function decorator will repeatedly apply a function while
/// the predicate returns a boolean that is true. If the predicate returns an
/// `IntergralConstant` then the predicate is only evaluated at compile-time.
///
///
/// Synopsis
/// --------
///
/// template<class Predicate>
/// constexpr auto repeat_while(Predicate predicate);
///
/// Requirements
/// ------------
///
/// Predicate must be:
///
/// * [ConstFunctionObject](ConstFunctionObject)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct increment
/// {
/// template<class T>
/// constexpr std::integral_constant<int, T::value + 1> operator()(T) const
/// {
/// return std::integral_constant<int, T::value + 1>();
/// }
/// };
///
/// struct not_6
/// {
/// template<class T>
/// constexpr std::integral_constant<bool, (T::value != 6)>
/// operator()(T) const
/// {
/// return std::integral_constant<bool, (T::value != 6)>();
/// }
/// };
///
/// typedef std::integral_constant<int, 1> one;
/// typedef std::integral_constant<int, 6> six;
///
/// int main() {
/// auto increment_until_6 = boost::hof::repeat_while(not_6())(increment());
/// static_assert(std::is_same<six, decltype(increment_until_6(one()))>::value, "Error");
/// }
///
#include <boost/hof/always.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/decorate.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/first_of.hpp>
#include <boost/hof/detail/recursive_constexpr_depth.hpp>
namespace boost { namespace hof { namespace detail {
template<class P, class... Ts>
struct compute_predicate
{
typedef decltype(std::declval<P>()(std::declval<Ts>()...)) type;
};
template<bool B>
struct while_repeater
{
template<class F, class P, class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(while_repeater<
compute_predicate<P, typename result_of<const F&, id_<Ts>...>::type>::type::value
>, id_<const F&>, id_<const P&>, result_of<const F&, id_<Ts>...>)
operator()(const F& f, const P& p, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
while_repeater<
compute_predicate<P, decltype(f(BOOST_HOF_FORWARD(Ts)(xs)...))>::type::value
>()(f, p, f(BOOST_HOF_FORWARD(Ts)(xs)...))
);
};
template<>
struct while_repeater<false>
{
template<class F, class P, class T>
constexpr T operator()(const F&, const P&, T&& x) const
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(x)
{
return x;
}
};
struct repeat_while_constant_decorator
{
template<class P, class F, class... Ts>
constexpr auto operator()(const P& p, const F& f, Ts&&... xs) const BOOST_HOF_RETURNS
(
detail::while_repeater<
detail::compute_predicate<P, decltype(std::declval<F>()(BOOST_HOF_FORWARD(Ts)(xs)...))>::type::value
>()
(
f,
p,
BOOST_HOF_FORWARD(Ts)(xs)...
)
);
};
template<int Depth>
struct repeat_while_integral_decorator
{
template<class P, class F, class T, class... Ts, class Self=repeat_while_integral_decorator<Depth-1>>
constexpr auto operator()(const P& p, const F& f, T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
(
(p(x, BOOST_HOF_FORWARD(Ts)(xs)...)) ?
Self()(
p,
f,
f(x, BOOST_HOF_FORWARD(Ts)(xs)...)
) :
BOOST_HOF_FORWARD(T)(x)
);
};
template<>
struct repeat_while_integral_decorator<0>
{
template<class P, class F, class T, class Self=repeat_while_integral_decorator<0>>
#if BOOST_HOF_HAS_RELAXED_CONSTEXPR
constexpr
#endif
auto operator()(const P& p, const F& f, T x) const
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((p(x), f(x)))
-> decltype(f(x))
{
while(p(x))
{
// TODO: Should move?
x = f(x);
}
return x;
}
};
}
#if BOOST_HOF_HAS_RELAXED_CONSTEXPR
#define BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH 1
#else
#define BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH
#endif
BOOST_HOF_DECLARE_STATIC_VAR(repeat_while, decorate_adaptor<
boost::hof::first_of_adaptor<
detail::repeat_while_constant_decorator,
detail::repeat_while_integral_decorator<BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH>
>
>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,135 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
result.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_RESULT_H
#define BOOST_HOF_GUARD_RESULT_H
/// result
/// ======
///
/// Description
/// -----------
///
/// The `result` function adaptor sets the return type for the function, which
/// can be useful when dealing with multiple overloads. Since the return type
/// is no longer dependent on the parameters passed to the function, the
/// `result_adaptor` provides a nested `result_type` that is the return type
/// of the function.
///
/// Synopsis
/// --------
///
/// template<class Result, class F>
/// constexpr result_adaptor<Result, F> result(F f);
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct id
/// {
/// template<class T>
/// T operator()(T x) const
/// {
/// return x;
/// }
/// };
///
/// int main() {
/// auto int_result = boost::hof::result<int>(id());
/// static_assert(std::is_same<decltype(int_result(true)), int>::value, "Not the same type");
/// }
///
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/is_invocable.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/reveal.hpp>
namespace boost { namespace hof {
template<class Result, class F>
struct result_adaptor : detail::callable_base<F>
{
BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>)
typedef Result result_type;
struct failure
: failure_for<detail::callable_base<F>>
{};
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return boost::hof::always_ref(*this)(xs...);
}
template<class... Ts, class=typename std::enable_if<(boost::hof::is_invocable<F, Ts...>::value)>::type>
constexpr result_type operator()(Ts&&... xs) const
{
return this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...);
};
};
template<class F>
struct result_adaptor<void, F> : detail::callable_base<F>
{
BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>)
typedef void result_type;
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return boost::hof::always_ref(*this)(xs...);
}
template<class... Ts, class=typename std::enable_if<(boost::hof::is_invocable<F, Ts...>::value)>::type>
constexpr typename detail::holder<Ts...>::type operator()(Ts&&... xs) const
{
return (typename detail::holder<Ts...>::type)this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...);
};
};
#if BOOST_HOF_HAS_VARIABLE_TEMPLATES
namespace result_detail {
template<class Result>
struct result_f
{
template<class F>
constexpr result_adaptor<Result, F> operator()(F f) const
{
return result_adaptor<Result, F>(boost::hof::move(f));
}
};
}
template<class Result>
static constexpr auto result = result_detail::result_f<Result>{};
#else
template<class Result, class F>
constexpr result_adaptor<Result, F> result(F f)
{
return result_adaptor<Result, F>(boost::hof::move(f));
}
#endif
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,249 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
returns.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_RETURNS_H
#define BOOST_HOF_GUARD_RETURNS_H
/// BOOST_HOF_RETURNS
/// ===========
///
/// Description
/// -----------
///
/// The `BOOST_HOF_RETURNS` macro defines the function as the expression
/// equivalence. It does this by deducing `noexcept` and the return type by
/// using a trailing `decltype`. Instead of repeating the expression for the
/// return type, `noexcept` clause and the function body, this macro will
/// reduce the code duplication from that.
///
/// Note: The expression used to deduce the return the type will also
/// constrain the template function and deduce `noexcept` as well, which is
/// different behaviour than using C++14's return type deduction.
///
/// Synopsis
/// --------
///
/// #define BOOST_HOF_RETURNS(...)
///
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// template<class T, class U>
/// auto sum(T x, U y) BOOST_HOF_RETURNS(x+y);
///
/// int main() {
/// assert(3 == sum(1, 2));
/// }
///
///
/// Incomplete this
/// ---------------
///
/// Description
/// -----------
///
/// On some non-conformant compilers, such as gcc, the `this` variable cannot
/// be used inside the `BOOST_HOF_RETURNS` macro because it is considered an
/// incomplete type. So the following macros are provided to help workaround
/// the issue.
///
///
/// Synopsis
/// --------
///
/// // Declares the type of the `this` variable
/// #define BOOST_HOF_RETURNS_CLASS(...)
/// // Used to refer to the `this` variable in the BOOST_HOF_RETURNS macro
/// #define BOOST_HOF_THIS
/// // Used to refer to the const `this` variable in the BOOST_HOF_RETURNS macro
/// #define BOOST_HOF_CONST_THIS
///
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct add_1
/// {
/// int a;
/// add_1() : a(1) {}
///
/// BOOST_HOF_RETURNS_CLASS(add_1);
///
/// template<class T>
/// auto operator()(T x) const
/// BOOST_HOF_RETURNS(x+BOOST_HOF_CONST_THIS->a);
/// };
///
/// int main() {
/// assert(3 == add_1()(2));
/// }
///
///
/// Mangling overloads
/// ------------------
///
/// Description
/// -----------
///
/// On older compilers some operations done in the expressions cannot be
/// properly mangled. These macros help provide workarounds for these
/// operations on older compilers.
///
///
/// Synopsis
/// --------
///
/// // Explicitly defines the type for name mangling
/// #define BOOST_HOF_MANGLE_CAST(...)
/// // C cast for name mangling
/// #define BOOST_HOF_RETURNS_C_CAST(...)
/// // Reinterpret cast for name mangling
/// #define BOOST_HOF_RETURNS_REINTERPRET_CAST(...)
/// // Static cast for name mangling
/// #define BOOST_HOF_RETURNS_STATIC_CAST(...)
/// // Construction for name mangling
/// #define BOOST_HOF_RETURNS_CONSTRUCT(...)
///
#include <boost/hof/config.hpp>
#include <utility>
#include <boost/hof/detail/forward.hpp>
#include <boost/hof/detail/noexcept.hpp>
#define BOOST_HOF_EAT(...)
#define BOOST_HOF_REM(...) __VA_ARGS__
#if BOOST_HOF_HAS_COMPLETE_DECLTYPE && BOOST_HOF_HAS_MANGLE_OVERLOAD
#ifdef _MSC_VER
// Since decltype can't be used in noexcept on MSVC, we can't check for noexcept
// move constructors.
#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(__VA_ARGS__))
#else
#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(static_cast<decltype(__VA_ARGS__)>(__VA_ARGS__)))
#endif
#define BOOST_HOF_RETURNS(...) \
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(__VA_ARGS__) \
-> decltype(__VA_ARGS__) { return __VA_ARGS__; }
#define BOOST_HOF_THIS this
#define BOOST_HOF_CONST_THIS this
#define BOOST_HOF_RETURNS_CLASS(...) \
void fit_returns_class_check() \
{ \
static_assert(std::is_same<__VA_ARGS__*, decltype(this)>::value, \
"Returns class " #__VA_ARGS__ " type doesn't match"); \
}
#define BOOST_HOF_MANGLE_CAST(...) BOOST_HOF_REM
#define BOOST_HOF_RETURNS_C_CAST(...) (__VA_ARGS__) BOOST_HOF_REM
#define BOOST_HOF_RETURNS_REINTERPRET_CAST(...) reinterpret_cast<__VA_ARGS__>
#define BOOST_HOF_RETURNS_STATIC_CAST(...) static_cast<__VA_ARGS__>
#define BOOST_HOF_RETURNS_CONSTRUCT(...) __VA_ARGS__
#else
#include <boost/hof/detail/pp.hpp>
#define BOOST_HOF_RETURNS_RETURN(...) return BOOST_HOF_RETURNS_RETURN_X(BOOST_HOF_PP_WALL(__VA_ARGS__))
#define BOOST_HOF_RETURNS_RETURN_X(...) __VA_ARGS__
#ifdef _MSC_VER
// Since decltype can't be used in noexcept on MSVC, we can't check for noexcept
// move constructors.
#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__)))
#else
#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(static_cast<decltype(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__))>(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__))))
#endif
#define BOOST_HOF_RETURNS_DECLTYPE(...) \
-> decltype(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__))
#define BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(...) BOOST_HOF_RETURNS_DECLTYPE_CONTEXT_X(BOOST_HOF_PP_WALL(__VA_ARGS__))
#define BOOST_HOF_RETURNS_DECLTYPE_CONTEXT_X(...) __VA_ARGS__
#define BOOST_HOF_RETURNS_THAT(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
(boost::hof::detail::check_this<__VA_ARGS__, decltype(this)>(), this), \
std::declval<__VA_ARGS__>() \
)
#define BOOST_HOF_THIS BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_THAT)(fit_this_type)
#define BOOST_HOF_CONST_THIS BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_THAT)(fit_const_this_type)
#define BOOST_HOF_RETURNS_CLASS(...) typedef __VA_ARGS__* fit_this_type; typedef const __VA_ARGS__* fit_const_this_type
#define BOOST_HOF_RETURNS(...) \
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(__VA_ARGS__) \
BOOST_HOF_RETURNS_DECLTYPE(__VA_ARGS__) \
{ BOOST_HOF_RETURNS_RETURN(__VA_ARGS__); }
namespace boost { namespace hof { namespace detail {
template<class Assumed, class T>
struct check_this
{
static_assert(std::is_same<T, Assumed>::value, "Incorret BOOST_HOF_THIS or BOOST_HOF_CONST_THIS used.");
};
}}} // namespace boost::hof
#endif
#if BOOST_HOF_HAS_MANGLE_OVERLOAD
#define BOOST_HOF_MANGLE_CAST(...) BOOST_HOF_REM
#define BOOST_HOF_RETURNS_C_CAST(...) (__VA_ARGS__) BOOST_HOF_REM
#define BOOST_HOF_RETURNS_REINTERPRET_CAST(...) reinterpret_cast<__VA_ARGS__>
#define BOOST_HOF_RETURNS_STATIC_CAST(...) static_cast<__VA_ARGS__>
#define BOOST_HOF_RETURNS_CONSTRUCT(...) __VA_ARGS__
#else
#define BOOST_HOF_RETURNS_DERAIL_MANGLE_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
BOOST_HOF_REM, \
std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
)
#define BOOST_HOF_MANGLE_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_MANGLE_CAST)
#define BOOST_HOF_RETURNS_DERAIL_C_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
(__VA_ARGS__) BOOST_HOF_REM, \
std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
)
#define BOOST_HOF_RETURNS_C_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_C_CAST)
#define BOOST_HOF_RETURNS_DERAIL_REINTERPRET_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
reinterpret_cast<__VA_ARGS__>, \
std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
)
#define BOOST_HOF_RETURNS_REINTERPRET_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_REINTERPRET_CAST)
#define BOOST_HOF_RETURNS_DERAIL_STATIC_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
static_cast<__VA_ARGS__>, \
std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
)
#define BOOST_HOF_RETURNS_STATIC_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_STATIC_CAST)
#define BOOST_HOF_RETURNS_DERAIL_CONSTRUCT(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
__VA_ARGS__, \
std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
)
#define BOOST_HOF_RETURNS_CONSTRUCT BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_CONSTRUCT)
#endif
#define BOOST_HOF_AUTO_FORWARD(...) BOOST_HOF_RETURNS_STATIC_CAST(decltype(__VA_ARGS__))(__VA_ARGS__)
#endif

View File

@@ -0,0 +1,385 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
reveal.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_REVEAL_H
#define BOOST_HOF_GUARD_FUNCTION_REVEAL_H
/// reveal
/// ======
///
/// Description
/// -----------
///
/// The `reveal` function adaptor helps shows the error messages that get
/// masked on some compilers. Sometimes an error in a function that causes a
/// substitution failure, will remove the function from valid overloads. On
/// compilers without a backtrace for substitution failure, this will mask the
/// error inside the function. The `reveal` adaptor will expose these error
/// messages while still keeping the function SFINAE-friendly.
///
/// Sample
/// ------
///
/// If we take the `print` example from the quick start guide like this:
///
/// namespace adl {
///
/// using std::begin;
///
/// template<class R>
/// auto adl_begin(R&& r) BOOST_HOF_RETURNS(begin(r));
/// }
///
/// BOOST_HOF_STATIC_LAMBDA_FUNCTION(for_each_tuple) = [](const auto& sequence, auto f) BOOST_HOF_RETURNS
/// (
/// boost::hof::unpack(boost::hof::proj(f))(sequence)
/// );
///
/// auto print = boost::hof::fix(boost::hof::first_of(
/// [](auto, const auto& x) -> decltype(std::cout << x, void())
/// {
/// std::cout << x << std::endl;
/// },
/// [](auto self, const auto& range) -> decltype(self(*adl::adl_begin(range)), void())
/// {
/// for(const auto& x:range) self(x);
/// },
/// [](auto self, const auto& tuple) -> decltype(for_each_tuple(tuple, self), void())
/// {
/// return for_each_tuple(tuple, self);
/// }
/// ));
///
/// Which prints numbers and vectors:
///
/// print(5);
///
/// std::vector<int> v = { 1, 2, 3, 4 };
/// print(v);
///
/// However, if we pass a type that can't be printed, we get an error like
/// this:
///
/// print.cpp:49:5: error: no matching function for call to object of type 'boost::hof::fix_adaptor<boost::hof::first_of_adaptor<(lambda at print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)> >'
/// print(foo{});
/// ^~~~~
/// fix.hpp:158:5: note: candidate template ignored: substitution failure [with Ts = <foo>]: no matching function for call to object of type 'const boost::hof::first_of_adaptor<(lambda at
/// print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)>'
/// operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
///
/// Which is short and gives very little information why it can't be called.
/// It doesn't even show the overloads that were try. However, using the
/// `reveal` adaptor we can get more info about the error like this:
///
/// print.cpp:49:5: error: no matching function for call to object of type 'boost::hof::reveal_adaptor<boost::hof::fix_adaptor<boost::hof::first_of_adaptor<(lambda at print.cpp:29:9), (lambda at print.cpp:33:9),
/// (lambda at print.cpp:37:9)> >, boost::hof::fix_adaptor<boost::hof::first_of_adaptor<(lambda at print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)> > >'
/// boost::hof::reveal(print)(foo{});
/// ^~~~~~~~~~~~~~~~~~
/// reveal.hpp:149:20: note: candidate template ignored: substitution failure [with Ts = <foo>, $1 = void]: no matching function for call to object of type '(lambda at print.cpp:29:9)'
/// constexpr auto operator()(Ts&&... xs) const
/// ^
/// reveal.hpp:149:20: note: candidate template ignored: substitution failure [with Ts = <foo>, $1 = void]: no matching function for call to object of type '(lambda at print.cpp:33:9)'
/// constexpr auto operator()(Ts&&... xs) const
/// ^
/// reveal.hpp:149:20: note: candidate template ignored: substitution failure [with Ts = <foo>, $1 = void]: no matching function for call to object of type '(lambda at print.cpp:37:9)'
/// constexpr auto operator()(Ts&&... xs) const
/// ^
/// fix.hpp:158:5: note: candidate template ignored: substitution failure [with Ts = <foo>]: no matching function for call to object of type 'const boost::hof::first_of_adaptor<(lambda at
/// print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)>'
/// operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
///
/// So now the error has a note for each of the lambda overloads it tried. Of
/// course this can be improved even further by providing custom reporting of
/// failures.
///
/// Synopsis
/// --------
///
/// template<class F>
/// reveal_adaptor<F> reveal(F f);
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Reporting Failures
/// ------------------
///
/// By default, `reveal` reports the substitution failure by trying to call
/// the function. However, more detail expressions can be be reported from a
/// template alias by using `as_failure`. This is done by defining a nested
/// `failure` struct in the function object and then inheriting from
/// `as_failure`. Also multiple failures can be reported by using
/// `with_failures`.
///
/// Synopsis
/// --------
///
/// // Report failure by instantiating the Template
/// template<template<class...> class Template>
/// struct as_failure;
///
/// // Report multiple falures
/// template<class... Failures>
/// struct with_failures;
///
/// // Report the failure for each function
/// template<class... Fs>
/// struct failure_for;
///
/// // Get the failure of a function
/// template<class F>
/// struct get_failure;
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct sum_f
/// {
/// template<class T, class U>
/// using sum_failure = decltype(std::declval<T>()+std::declval<U>());
///
/// struct failure
/// : boost::hof::as_failure<sum_failure>
/// {};
///
/// template<class T, class U>
/// auto operator()(T x, U y) const BOOST_HOF_RETURNS(x+y);
/// };
///
/// int main() {
/// assert(sum_f()(1, 2) == 3);
/// }
///
#include <boost/hof/always.hpp>
#include <boost/hof/returns.hpp>
#include <boost/hof/is_invocable.hpp>
#include <boost/hof/identity.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/holder.hpp>
#include <boost/hof/detail/join.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
#include <boost/hof/detail/using.hpp>
#ifndef BOOST_HOF_REVEAL_USE_TEMPLATE_ALIAS
#ifdef __clang__
#define BOOST_HOF_REVEAL_USE_TEMPLATE_ALIAS 1
#else
#define BOOST_HOF_REVEAL_USE_TEMPLATE_ALIAS 0
#endif
#endif
namespace boost { namespace hof {
namespace detail {
template<class T, class=void>
struct has_failure
: std::false_type
{};
template<class T>
struct has_failure<T, typename holder<
typename T::failure
>::type>
: std::true_type
{};
struct identity_failure
{
template<class T>
T operator()(T&& x);
template<class T>
static T&& val();
#if BOOST_HOF_REVEAL_USE_TEMPLATE_ALIAS
template<template<class...> class Template, class... Ts>
BOOST_HOF_USING(defer, Template<Ts...>);
#else
template<template<class...> class Template, class... Ts>
static auto defer(Ts&&...) -> Template<Ts...>;
#endif
};
}
template<class F, class=void>
struct get_failure
{
template<class... Ts>
struct of
{
#if BOOST_HOF_REVEAL_USE_TEMPLATE_ALIAS
template<class Id>
using apply = decltype(Id()(std::declval<F>())(std::declval<Ts>()...));
#else
template<class Id>
static auto apply(Id id) -> decltype(id(std::declval<F>())(std::declval<Ts>()...));
#endif
};
};
template<class F>
struct get_failure<F, typename std::enable_if<detail::has_failure<F>::value>::type>
: F::failure
{};
template<template<class...> class Template>
struct as_failure
{
template<class... Ts>
struct of
{
#if BOOST_HOF_REVEAL_USE_TEMPLATE_ALIAS
template<class Id>
using apply = typename Id::template defer<Template, Ts...>;
#else
template<class Id>
static auto apply(Id) -> decltype(Id::template defer<Template, Ts...>());
#endif
};
};
namespace detail {
template<class Failure, class... Ts>
BOOST_HOF_USING_TYPENAME(apply_failure, Failure::template of<Ts...>);
template<class F, class Failure>
struct reveal_failure
{
// Add default constructor to make clang 3.4 happy
constexpr reveal_failure()
{}
// This is just a placeholder to produce a note in the compiler, it is
// never called
template<
class... Ts,
class=typename std::enable_if<(!is_invocable<F, Ts...>::value)>::type
>
constexpr auto operator()(Ts&&... xs) const
#if BOOST_HOF_REVEAL_USE_TEMPLATE_ALIAS
-> typename apply_failure<Failure, Ts...>::template apply<boost::hof::detail::identity_failure>;
#else
-> decltype(apply_failure<Failure, Ts...>::apply(boost::hof::detail::identity_failure()));
#endif
};
template<class F, class Failure=get_failure<F>, class=void>
struct traverse_failure
: reveal_failure<F, Failure>
{
constexpr traverse_failure()
{}
};
template<class F, class Failure>
struct traverse_failure<F, Failure, typename holder<
typename Failure::children
>::type>
: Failure::children::template overloads<F>
{
constexpr traverse_failure()
{}
};
template<class Failure, class Transform, class=void>
struct transform_failures
: Transform::template apply<Failure>
{};
template<class Failure, class Transform>
struct transform_failures<Failure, Transform, typename holder<
typename Failure::children
>::type>
: Failure::children::template transform<Transform>
{};
}
template<class Failure, class... Failures>
struct failures;
template<class... Fs>
struct with_failures
{
typedef BOOST_HOF_JOIN(failures, Fs...) children;
};
template<class Failure, class... Failures>
struct failures
{
template<class Transform>
BOOST_HOF_USING(transform, with_failures<detail::transform_failures<Failure, Transform>, detail::transform_failures<Failures, Transform>...>);
template<class F, class FailureBase=BOOST_HOF_JOIN(failures, Failures...)>
struct overloads
: detail::traverse_failure<F, Failure>, FailureBase::template overloads<F>
{
constexpr overloads()
{}
using detail::traverse_failure<F, Failure>::operator();
using FailureBase::template overloads<F>::operator();
};
};
template<class Failure>
struct failures<Failure>
{
template<class Transform>
BOOST_HOF_USING(transform, with_failures<detail::transform_failures<Failure, Transform>>);
template<class F>
BOOST_HOF_USING(overloads, detail::traverse_failure<F, Failure>);
};
template<class Transform, class... Fs>
struct failure_map
: with_failures<detail::transform_failures<get_failure<Fs>, Transform>...>
{};
template<class... Fs>
struct failure_for
: with_failures<get_failure<Fs>...>
{};
template<class F, class Base=detail::callable_base<F>>
struct reveal_adaptor
: detail::traverse_failure<Base>, Base
{
typedef reveal_adaptor fit_rewritable1_tag;
using detail::traverse_failure<Base>::operator();
using Base::operator();
BOOST_HOF_INHERIT_CONSTRUCTOR(reveal_adaptor, Base);
};
// Avoid double reveals, it causes problem on gcc 4.6
template<class F>
struct reveal_adaptor<reveal_adaptor<F>>
: reveal_adaptor<F>
{
typedef reveal_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(reveal_adaptor, reveal_adaptor<F>);
};
BOOST_HOF_DECLARE_STATIC_VAR(reveal, detail::make<reveal_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,173 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
reverse_fold.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_REVERSE_FOLD_H
#define BOOST_HOF_GUARD_REVERSE_FOLD_H
/// reverse_fold
/// ========
///
/// Description
/// -----------
///
/// The `reverse_fold` function adaptor uses a binary function to apply a
/// reverse [fold]
/// (https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29)(ie right
/// fold in functional programming terms) operation to the arguments passed to
/// the function. Additionally, an optional initial state can be provided,
/// otherwise the first argument is used as the initial state.
///
/// The arguments to the binary function, take first the state and then the
/// argument.
///
/// Synopsis
/// --------
///
/// template<class F, class State>
/// constexpr reverse_fold_adaptor<F, State> reverse_fold(F f, State s);
///
/// template<class F>
/// constexpr reverse_fold_adaptor<F> reverse_fold(F f);
///
/// Semantics
/// ---------
///
/// assert(reverse_fold(f, z)() == z);
/// assert(reverse_fold(f, z)(x, xs...) == f(reverse_fold(f, z)(xs...), x));
/// assert(reverse_fold(f)(x) == x);
/// assert(reverse_fold(f)(x, xs...) == f(reverse_fold(f)(xs...), x));
///
/// Requirements
/// ------------
///
/// State must be:
///
/// * CopyConstructible
///
/// F must be:
///
/// * [BinaryInvocable](BinaryInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct max_f
/// {
/// template<class T, class U>
/// constexpr T operator()(T x, U y) const
/// {
/// return x > y ? x : y;
/// }
/// };
///
/// int main() {
/// assert(boost::hof::reverse_fold(max_f())(2, 3, 4, 5) == 5);
/// }
///
/// References
/// ----------
///
/// * [Projections](Projections)
/// * [Variadic print](<Variadic print>)
///
#include <boost/hof/detail/callable_base.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/compressed_pair.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof { namespace detail {
struct v_reverse_fold
{
BOOST_HOF_RETURNS_CLASS(v_reverse_fold);
template<class F, class State, class T, class... Ts>
constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(const F&, result_of<const v_reverse_fold&, id_<const F&>, id_<State>, id_<Ts>...>, id_<T>)
operator()(const F& f, State&& state, T&& x, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
(
f((*BOOST_HOF_CONST_THIS)(f, BOOST_HOF_FORWARD(State)(state), BOOST_HOF_FORWARD(Ts)(xs)...), BOOST_HOF_FORWARD(T)(x))
);
template<class F, class State>
constexpr State operator()(const F&, State&& state) const noexcept
{
return BOOST_HOF_FORWARD(State)(state);
}
};
}
template<class F, class State=void>
struct reverse_fold_adaptor
: detail::compressed_pair<detail::callable_base<F>, State>
{
typedef detail::compressed_pair<detail::callable_base<F>, State> base_type;
BOOST_HOF_INHERIT_CONSTRUCTOR(reverse_fold_adaptor, base_type)
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return this->first(xs...);
}
template<class... Ts>
constexpr State get_state(Ts&&... xs) const noexcept
{
return this->second(xs...);
}
BOOST_HOF_RETURNS_CLASS(reverse_fold_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<State>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
detail::v_reverse_fold()(
BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
BOOST_HOF_MANGLE_CAST(State)(BOOST_HOF_CONST_THIS->get_state(xs...)),
BOOST_HOF_FORWARD(Ts)(xs)...
)
)
};
template<class F>
struct reverse_fold_adaptor<F, void>
: detail::callable_base<F>
{
BOOST_HOF_INHERIT_CONSTRUCTOR(reverse_fold_adaptor, detail::callable_base<F>)
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
BOOST_HOF_RETURNS_CLASS(reverse_fold_adaptor);
template<class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<Ts>...)
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
detail::v_reverse_fold()(
BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
BOOST_HOF_FORWARD(Ts)(xs)...
)
)
};
BOOST_HOF_DECLARE_STATIC_VAR(reverse_fold, detail::make<reverse_fold_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,101 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
rotate.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_ROTATE_H
#define BOOST_HOF_GUARD_ROTATE_H
/// rotate
/// ====
///
/// Description
/// -----------
///
/// The `rotate` function adaptor moves the first parameter to the last
/// parameter.
///
/// Synopsis
/// --------
///
/// template<class F>
/// rotate_adaptor<F> rotate(F f);
///
/// Semantics
/// ---------
///
/// assert(rotate(f)(x, xs...) == f(xs..., x));
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// int main() {
/// int r = boost::hof::rotate(boost::hof::_ - boost::hof::_)(2, 5);
/// assert(r == 3);
/// }
///
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
template<class F>
struct rotate_adaptor : detail::callable_base<F>
{
typedef rotate_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(rotate_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
struct rotate_failure
{
template<class Failure>
struct apply
{
template<class T, class... Ts>
struct of
: Failure::template of<Ts..., T>
{};
};
};
struct failure
: failure_map<rotate_failure, detail::callable_base<F>>
{};
BOOST_HOF_RETURNS_CLASS(rotate_adaptor);
template<class T, class... Ts>
constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F>&, id_<Ts>..., id_<T>)
operator()(T&& x, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
(
(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
(BOOST_HOF_FORWARD(Ts)(xs)..., BOOST_HOF_FORWARD(T)(x))
);
};
BOOST_HOF_DECLARE_STATIC_VAR(rotate, detail::make<rotate_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,97 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
static.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_STATIC_H
#define BOOST_HOF_GUARD_FUNCTION_STATIC_H
/// static
/// ======
///
/// Description
/// -----------
///
/// The `static_` adaptor is a static function adaptor that allows any
/// default-constructible function object to be static-initialized. Functions
/// initialized by `static_` cannot be used in `constexpr` functions. If the
/// function needs to be statically initialized and called in a `constexpr`
/// context, then a `constexpr` constructor needs to be used rather than
/// `static_`.
///
/// Synopsis
/// --------
///
/// template<class F>
/// class static_;
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstFunctionObject](ConstFunctionObject)
/// * DefaultConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// // In C++ this class can't be static-initialized, because of the non-
/// // trivial default constructor.
/// struct times_function
/// {
/// double factor;
/// times_function() : factor(2)
/// {}
/// template<class T>
/// T operator()(T x) const
/// {
/// return x*factor;
/// }
/// };
///
/// static constexpr static_<times_function> times2 = {};
///
/// int main() {
/// assert(6 == times2(3));
/// }
///
#include <boost/hof/detail/result_of.hpp>
#include <boost/hof/reveal.hpp>
namespace boost { namespace hof {
template<class F>
struct static_
{
struct failure
: failure_for<F>
{};
const F& base_function() const
BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(F)
{
static F f;
return f;
}
BOOST_HOF_RETURNS_CLASS(static_);
template<class... Ts>
BOOST_HOF_SFINAE_RESULT(F, id_<Ts>...)
operator()(Ts && ... xs) const
BOOST_HOF_SFINAE_RETURNS(BOOST_HOF_CONST_THIS->base_function()(BOOST_HOF_FORWARD(Ts)(xs)...));
};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,83 @@
/*=============================================================================
Copyright (c) 2014 Paul Fultz II
tap.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_TAP_H
#define BOOST_HOF_GUARD_FUNCTION_TAP_H
/// tap
/// ===
///
/// Description
/// -----------
///
/// The `tap` function invokes a function on the first argument passed in and
/// then returns the first argument. This is useful in a chain of pipable
/// function to perform operations on intermediate results. As a result, this
/// function is [`pipable`](/include/boost/hof/pipable).
///
/// Synopsis
/// --------
///
/// template<class T, class F>
/// pipable constexpr T tap(T&& x, const F& f);
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [UnaryInvocable](UnaryInvocable)
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// #include <iostream>
/// using namespace boost::hof;
///
/// struct sum_f
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// const pipable_adaptor<sum_f> sum = {};
/// int main() {
/// // Prints 3
/// int r = 1 | sum(2) | tap([](int i) { std::cout << i; }) | sum(2);
/// assert(r == 5);
/// }
///
#include <boost/hof/pipable.hpp>
#include <boost/hof/apply.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof { namespace detail {
struct tap_f
{
template<class T, class F>
constexpr T operator()(T&& x, const F& f) const
BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((boost::hof::apply(f, x), BOOST_HOF_FORWARD(T)(x)))
{
return boost::hof::apply(f, x), BOOST_HOF_FORWARD(T)(x);
}
};
}
BOOST_HOF_DECLARE_STATIC_VAR(tap, pipable_adaptor<detail::tap_f>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,181 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
unpack.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_UNPACK_H
#define BOOST_HOF_GUARD_UNPACK_H
/// unpack
/// ======
///
/// Description
/// -----------
///
/// The `unpack` function adaptor takes a sequence and uses the elements of
/// the sequence for the arguments to the function. Multiple sequences can be
/// passed to the function. All elements from each sequence will be passed
/// into the function.
///
///
/// Synopsis
/// --------
///
/// template<class F>
/// unpack_adaptor<F> unpack(F f);
///
/// Requirements
/// ------------
///
/// F must be:
///
/// * [ConstInvocable](ConstInvocable)
/// * MoveConstructible
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
/// using namespace boost::hof;
///
/// struct sum
/// {
/// template<class T, class U>
/// T operator()(T x, U y) const
/// {
/// return x+y;
/// }
/// };
///
/// int main() {
/// int r = unpack(sum())(std::make_tuple(3,2));
/// assert(r == 5);
/// }
///
/// References
/// ----------
///
/// * [std::apply](http://en.cppreference.com/w/cpp/utility/apply) - C++17 function to unpack a tuple
/// * [`unpack_sequence`](unpack_sequence)
///
#include <boost/hof/unpack_sequence.hpp>
#include <boost/hof/is_unpackable.hpp>
#include <boost/hof/detail/seq.hpp>
#include <boost/hof/capture.hpp>
#include <boost/hof/always.hpp>
#include <boost/hof/reveal.hpp>
#include <boost/hof/detail/and.hpp>
#include <boost/hof/detail/delegate.hpp>
#include <boost/hof/detail/holder.hpp>
#include <boost/hof/detail/move.hpp>
#include <boost/hof/detail/make.hpp>
#include <boost/hof/detail/static_const_var.hpp>
namespace boost { namespace hof {
namespace detail {
template<class F, class Sequence>
constexpr auto unpack_simple(F&& f, Sequence&& s) BOOST_HOF_RETURNS
(
detail::unpack_impl(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(Sequence)(s))
)
template<class F, class... Sequences>
constexpr auto unpack_join(F&& f, Sequences&&... s) BOOST_HOF_RETURNS
(
boost::hof::pack_join(unpack_simple(boost::hof::pack_forward, BOOST_HOF_FORWARD(Sequences)(s))...)(BOOST_HOF_FORWARD(F)(f))
);
}
template<class F>
struct unpack_adaptor : detail::callable_base<F>
{
typedef unpack_adaptor fit_rewritable1_tag;
BOOST_HOF_INHERIT_CONSTRUCTOR(unpack_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
{
return boost::hof::always_ref(*this)(xs...);
}
struct unpack_failure
{
template<class Failure>
struct apply
{
struct deducer
{
template<class... Ts>
typename Failure::template of<Ts...> operator()(Ts&&...) const;
};
template<class T, class=typename std::enable_if<(
is_unpackable<T>::value
)>::type>
static auto deduce(T&& x)
BOOST_HOF_RETURNS
(
boost::hof::detail::unpack_simple(deducer(), BOOST_HOF_FORWARD(T)(x))
);
template<class T, class... Ts, class=typename std::enable_if<(
is_unpackable<T>::value && BOOST_HOF_AND_UNPACK(is_unpackable<Ts>::value)
)>::type>
static auto deduce(T&& x, Ts&&... xs) BOOST_HOF_RETURNS
(
boost::hof::detail::unpack_join(deducer(), BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)
);
#ifdef _MSC_VER
template<class... Ts>
struct nop_failure;
template<class... Ts, class=typename std::enable_if<(
!BOOST_HOF_AND_UNPACK(is_unpackable<Ts>::value)
)>::type>
static as_failure<nop_failure> deduce(Ts&&... xs);
#endif
template<class... Ts>
struct of
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) || defined (_MSC_VER)
: std::enable_if<true, decltype(apply::deduce(std::declval<Ts>()...))>::type
#else
: decltype(apply::deduce(std::declval<Ts>()...))
#endif
{};
};
};
struct failure
: failure_map<unpack_failure, detail::callable_base<F>>
{};
BOOST_HOF_RETURNS_CLASS(unpack_adaptor);
template<class T, class=typename std::enable_if<(
is_unpackable<T>::value
)>::type>
constexpr auto operator()(T&& x) const
BOOST_HOF_RETURNS
(
boost::hof::detail::unpack_simple(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(x)), BOOST_HOF_FORWARD(T)(x))
);
template<class T, class... Ts, class=typename std::enable_if<(
is_unpackable<T>::value && BOOST_HOF_AND_UNPACK(is_unpackable<Ts>::value)
)>::type>
constexpr auto operator()(T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
(
boost::hof::detail::unpack_join(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(x)), BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)
);
};
BOOST_HOF_DECLARE_STATIC_VAR(unpack, detail::make<unpack_adaptor>);
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,71 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
unpack_sequence.hpp
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_UNPACK_SEQUENCE_HPP
#define BOOST_HOF_GUARD_UNPACK_SEQUENCE_HPP
/// unpack_sequence
/// ===============
///
/// How to unpack a sequence can be defined by specializing `unpack_sequence`.
/// By default, `std::tuple` is already specialized. To implement this, one
/// needs to provide a static `apply` function which will unpack the sequence
/// to the parameters of the function.
///
/// Synopsis
/// --------
///
/// template<class Sequence, class=void>
/// struct unpack_sequence;
///
/// Example
/// -------
///
/// #include <boost/hof.hpp>
/// #include <cassert>
///
/// struct my_sequence
/// {
/// int x;
/// int y;
/// };
///
/// namespace boost { namespace hof {
/// template<>
/// struct unpack_sequence<my_sequence>
/// {
/// template<class F, class Sequence>
/// constexpr static auto apply(F&& f, Sequence&& s) BOOST_HOF_RETURNS
/// (
/// f(s.x, s.y)
/// );
/// };
/// }} // namespace boost::hof
///
/// int main() {
/// }
///
/// See Also
/// --------
///
/// * [unpack](unpack)
/// * [is_unpackable](is_unpackable)
///
#include <boost/hof/config.hpp>
namespace boost { namespace hof {
template<class Sequence, class=void>
struct unpack_sequence
{
typedef void not_unpackable;
};
}} // namespace boost::hof
#endif

View File

@@ -0,0 +1,16 @@
/*=============================================================================
Copyright (c) 2016 Paul Fultz II
version.hpp
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_VERSION_HPP
#define BOOST_HOF_GUARD_VERSION_HPP
#define BOOST_HOF_VERSION_MAJOR 0
#define BOOST_HOF_VERSION_MINOR 6
#define BOOST_HOF_VERSION_PATCH 0
#define BOOST_HOF_VERSION (((BOOST_HOF_VERSION_MAJOR) << 24) + ((BOOST_HOF_VERSION_MINOR) << 16) + (BOOST_HOF_VERSION_PATCH))
#endif