/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to 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) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_FUNCTIONAL_PIPEABLE_HPP #define RANGES_V3_FUNCTIONAL_PIPEABLE_HPP #include #include #include namespace ranges { /// \addtogroup group-functional /// @{ struct pipeable_base; template RANGES_INLINE_VAR constexpr bool is_pipeable_v = META_IS_BASE_OF(pipeable_base, T); template RANGES_INLINE_VAR constexpr bool is_pipeable_v = META_IS_BASE_OF(pipeable_base, T); template RANGES_INLINE_VAR constexpr bool is_pipeable_v = META_IS_BASE_OF(pipeable_base, T); template using is_pipeable = meta::bool_>; struct pipeable_access { template struct impl : Pipeable { using Pipeable::pipe; }; }; struct pipeable_base { private: friend pipeable_access; template struct composed; // Evaluate the pipe with an argument CPP_template(typename Arg, typename Pipe)( // requires(!is_pipeable_v) && is_pipeable_v) // clang-format off constexpr friend auto operator|(Arg &&arg, Pipe pipe) // clang-format off { return pipeable_access::impl::pipe(static_cast(arg), pipe); } // Compose two pipes CPP_template(typename Pipe0, typename Pipe1)( // requires is_pipeable_v && is_pipeable_v) // clang-format off constexpr friend auto operator|(Pipe0 pipe0, Pipe1 pipe1) // clang-format on { return composed{pipe0, pipe1}; } // Default Pipe behavior just passes the argument to the pipe's function call // operator // clang-format off template constexpr static auto CPP_auto_fun(pipe)(Arg &&arg, Pipe p) ( return static_cast(p)(static_cast(arg)) ) // clang-format on }; template struct pipeable_base::composed : pipeable_base { Pipe0 pipe0_; Pipe1 pipe1_; constexpr composed(Pipe0 pipe0, Pipe1 pipe1) : pipe0_(static_cast(pipe0)) , pipe1_(static_cast(pipe1)) {} // clang-format off template constexpr auto CPP_auto_fun(operator())(Arg &&arg) (const) ( return static_cast(arg) | pipe0_ | pipe1_ ) // clang-format on }; struct make_pipeable_fn { template constexpr auto operator()(Fun fun) const { struct _ : Fun , pipeable_base { constexpr explicit _(Fun && f) : Fun(static_cast(f)) {} }; return _{static_cast(fun)}; } }; /// \ingroup group-functional /// \sa `make_pipeable_fn` RANGES_INLINE_VARIABLE(make_pipeable_fn, make_pipeable) template using pipeable RANGES_DEPRECATED("Please use pipeable_base instead") = pipeable_base; /// \endcond /// @} } // namespace ranges #endif