summaryrefslogtreecommitdiff
path: root/boost/hof/proj.hpp
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:12:59 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:12:59 +0900
commitb8cf34c691623e4ec329053cbbf68522a855882d (patch)
tree34da08632a99677f6b79ecb65e5b655a5b69a67f /boost/hof/proj.hpp
parent3fdc3e5ee96dca5b11d1694975a65200787eab86 (diff)
downloadboost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.gz
boost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.bz2
boost-b8cf34c691623e4ec329053cbbf68522a855882d.zip
Imported Upstream version 1.67.0upstream/1.67.0
Diffstat (limited to 'boost/hof/proj.hpp')
-rw-r--r--boost/hof/proj.hpp265
1 files changed, 265 insertions, 0 deletions
diff --git a/boost/hof/proj.hpp b/boost/hof/proj.hpp
new file mode 100644
index 0000000000..6469186c87
--- /dev/null
+++ b/boost/hof/proj.hpp
@@ -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> by(Projection p, F f);
+///
+/// template<class Projection>
+/// constexpr proj_adaptor<Projection> by(Projection p);
+///
+/// Semantics
+/// ---------
+///
+/// assert(by(p, f)(xs...) == f(p(xs)...));
+/// assert(by(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