// Copyright (C) 2022 T. Zachary Laine // // 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_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP #define BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP #include #include namespace boost { namespace stl_interfaces { namespace detail { template using remove_cvref_t = std::remove_cv_t>; struct pipeable_base; #if BOOST_STL_INTERFACES_USE_CONCEPTS template concept pipeable_ = std::derived_from && std::is_object_v && std::copy_constructible; #else template constexpr bool pipeable_ = std::is_base_of::value && std::is_object::value && std::is_copy_constructible::value; #endif #if BOOST_STL_INTERFACES_USE_CONCEPTS template #else template< typename T, typename U, typename Enable = std::enable_if_t && pipeable_>> #endif struct view_pipeline; struct pipeable_base { #if BOOST_STL_INTERFACES_USE_CONCEPTS template requires std::constructible_from, T> && std::constructible_from, U> #else template< typename T, typename U, typename Enable = std::enable_if_t< pipeable_ && pipeable_ && std::is_constructible, T>::value && std::is_constructible, U>::value>> #endif friend constexpr auto operator|(T && t, U && u) { return view_pipeline{(T &&) t, (U &&) u}; } }; template struct pipeable : pipeable_base { template friend constexpr auto operator|(R && r, Derived & d) -> decltype(((Derived &&) d)((R &&) r)) { return ((Derived &&) d)((R &&) r); } template friend constexpr auto operator|(R && r, Derived const & d) -> decltype(((Derived &&) d)((R &&) r)) { return ((Derived &&) d)((R &&) r); } template friend constexpr auto operator|(R && r, Derived && d) -> decltype(((Derived &&) d)((R &&) r)) { return ((Derived &&) d)((R &&) r); } }; #if BOOST_STL_INTERFACES_USE_CONCEPTS template #else template #endif struct view_pipeline : pipeable> { view_pipeline() = default; constexpr view_pipeline(T && t, U && u) : left_(std::move(t)), right_(std::move(u)) {} #if BOOST_STL_INTERFACES_USE_CONCEPTS template requires std::invocable && std::invocable> constexpr decltype(auto) operator()(R && r) & #else template constexpr auto operator()(R && r) & -> decltype(this->right_(this->left_((R &&) r))) #endif { return right_(left_((R &&) r)); } #if BOOST_STL_INTERFACES_USE_CONCEPTS template requires std::invocable && std::invocable> constexpr decltype(auto) operator()(R && r) const & #else template constexpr auto operator()( R && r) const & -> decltype(this->right_(this->left_((R &&) r))) #endif { return right_(left_((R &&) r)); } #if BOOST_STL_INTERFACES_USE_CONCEPTS template requires std::invocable && std::invocable> constexpr decltype(auto) operator()(R && r) && #else template constexpr auto operator()(R && r) && -> decltype(std::move( this->right_)(std::move(this->left_)((R &&) r))) #endif { return std::move(right_)(std::move(left_)((R &&) r)); } T left_; U right_; }; }}} #endif