diff options
Diffstat (limited to 'boost/hof/detail')
23 files changed, 1371 insertions, 0 deletions
diff --git a/boost/hof/detail/and.hpp b/boost/hof/detail/and.hpp new file mode 100644 index 0000000000..8a7e50a36e --- /dev/null +++ b/boost/hof/detail/and.hpp @@ -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 diff --git a/boost/hof/detail/callable_base.hpp b/boost/hof/detail/callable_base.hpp new file mode 100644 index 0000000000..b214043e0b --- /dev/null +++ b/boost/hof/detail/callable_base.hpp @@ -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 diff --git a/boost/hof/detail/can_be_called.hpp b/boost/hof/detail/can_be_called.hpp new file mode 100644 index 0000000000..7cf6751da8 --- /dev/null +++ b/boost/hof/detail/can_be_called.hpp @@ -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 diff --git a/boost/hof/detail/compressed_pair.hpp b/boost/hof/detail/compressed_pair.hpp new file mode 100644 index 0000000000..b7c320e2da --- /dev/null +++ b/boost/hof/detail/compressed_pair.hpp @@ -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 diff --git a/boost/hof/detail/constexpr_deduce.hpp b/boost/hof/detail/constexpr_deduce.hpp new file mode 100644 index 0000000000..80bdd5ed8a --- /dev/null +++ b/boost/hof/detail/constexpr_deduce.hpp @@ -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 diff --git a/boost/hof/detail/delegate.hpp b/boost/hof/detail/delegate.hpp new file mode 100644 index 0000000000..af2179680d --- /dev/null +++ b/boost/hof/detail/delegate.hpp @@ -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 diff --git a/boost/hof/detail/forward.hpp b/boost/hof/detail/forward.hpp new file mode 100644 index 0000000000..729436c4aa --- /dev/null +++ b/boost/hof/detail/forward.hpp @@ -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 diff --git a/boost/hof/detail/holder.hpp b/boost/hof/detail/holder.hpp new file mode 100644 index 0000000000..4a7aed2093 --- /dev/null +++ b/boost/hof/detail/holder.hpp @@ -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 diff --git a/boost/hof/detail/intrinsics.hpp b/boost/hof/detail/intrinsics.hpp new file mode 100644 index 0000000000..1ace7d6882 --- /dev/null +++ b/boost/hof/detail/intrinsics.hpp @@ -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 diff --git a/boost/hof/detail/join.hpp b/boost/hof/detail/join.hpp new file mode 100644 index 0000000000..23ed8437d3 --- /dev/null +++ b/boost/hof/detail/join.hpp @@ -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 diff --git a/boost/hof/detail/make.hpp b/boost/hof/detail/make.hpp new file mode 100644 index 0000000000..791e1283a2 --- /dev/null +++ b/boost/hof/detail/make.hpp @@ -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 diff --git a/boost/hof/detail/move.hpp b/boost/hof/detail/move.hpp new file mode 100644 index 0000000000..bdbf73ddc7 --- /dev/null +++ b/boost/hof/detail/move.hpp @@ -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 diff --git a/boost/hof/detail/noexcept.hpp b/boost/hof/detail/noexcept.hpp new file mode 100644 index 0000000000..c7078a8b27 --- /dev/null +++ b/boost/hof/detail/noexcept.hpp @@ -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 diff --git a/boost/hof/detail/pp.hpp b/boost/hof/detail/pp.hpp new file mode 100644 index 0000000000..20bc7a960e --- /dev/null +++ b/boost/hof/detail/pp.hpp @@ -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 diff --git a/boost/hof/detail/recursive_constexpr_depth.hpp b/boost/hof/detail/recursive_constexpr_depth.hpp new file mode 100644 index 0000000000..1f4e630d35 --- /dev/null +++ b/boost/hof/detail/recursive_constexpr_depth.hpp @@ -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 diff --git a/boost/hof/detail/remove_rvalue_reference.hpp b/boost/hof/detail/remove_rvalue_reference.hpp new file mode 100644 index 0000000000..7de2879eaf --- /dev/null +++ b/boost/hof/detail/remove_rvalue_reference.hpp @@ -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 diff --git a/boost/hof/detail/result_of.hpp b/boost/hof/detail/result_of.hpp new file mode 100644 index 0000000000..6beccb9d2d --- /dev/null +++ b/boost/hof/detail/result_of.hpp @@ -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 diff --git a/boost/hof/detail/result_type.hpp b/boost/hof/detail/result_type.hpp new file mode 100644 index 0000000000..ce570baab6 --- /dev/null +++ b/boost/hof/detail/result_type.hpp @@ -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 diff --git a/boost/hof/detail/seq.hpp b/boost/hof/detail/seq.hpp new file mode 100644 index 0000000000..9f9f686c1a --- /dev/null +++ b/boost/hof/detail/seq.hpp @@ -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 diff --git a/boost/hof/detail/static_const_var.hpp b/boost/hof/detail/static_const_var.hpp new file mode 100644 index 0000000000..553bd23294 --- /dev/null +++ b/boost/hof/detail/static_const_var.hpp @@ -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 diff --git a/boost/hof/detail/unpack_tuple.hpp b/boost/hof/detail/unpack_tuple.hpp new file mode 100644 index 0000000000..19b0e853f8 --- /dev/null +++ b/boost/hof/detail/unpack_tuple.hpp @@ -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 diff --git a/boost/hof/detail/unwrap.hpp b/boost/hof/detail/unwrap.hpp new file mode 100644 index 0000000000..c9361d891e --- /dev/null +++ b/boost/hof/detail/unwrap.hpp @@ -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 diff --git a/boost/hof/detail/using.hpp b/boost/hof/detail/using.hpp new file mode 100644 index 0000000000..1f320d8337 --- /dev/null +++ b/boost/hof/detail/using.hpp @@ -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 |