diff options
Diffstat (limited to 'boost/hof/if.hpp')
-rw-r--r-- | boost/hof/if.hpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/boost/hof/if.hpp b/boost/hof/if.hpp new file mode 100644 index 0000000000..9eb199f11f --- /dev/null +++ b/boost/hof/if.hpp @@ -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 |