/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout 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 SPROUT_UTILITY_FOLD_HPP #define SPROUT_UTILITY_FOLD_HPP #include #include #include namespace sprout { template class folder_forwarder { public: typedef BinaryOperation function_type; private: function_type binary_op_; public: explicit SPROUT_CONSTEXPR folder_forwarder(function_type const& binary_op) : binary_op_(binary_op) {} SPROUT_CONSTEXPR function_type const& func() const { return binary_op_; } }; template class folder { public: typedef BinaryOperation function_type; typedef T value_type; private: function_type binary_op_; value_type value_; public: explicit SPROUT_CONSTEXPR folder(function_type const& binary_op, value_type const& value) : binary_op_(binary_op), value_(value) {} template SPROUT_CXX14_CONSTEXPR folder& left(U&& val) { return (value_ = binary_op_(value_, SPROUT_FORWARD(U, val))), *this; } template SPROUT_CXX14_CONSTEXPR folder& right(U&& val) { return (value_ = binary_op_(SPROUT_FORWARD(U, val), value_)), *this; } SPROUT_CONSTEXPR function_type const& func() const { return binary_op_; } SPROUT_CONSTEXPR value_type value() const { return value_; } SPROUT_CONSTEXPR value_type get() const { return value_; } SPROUT_CONSTEXPR operator value_type() const { return value_; } }; template inline SPROUT_CONSTEXPR sprout::folder operator,(sprout::folder_forwarder const& lhs, T&& rhs) { return sprout::folder(lhs.func(), SPROUT_FORWARD(T, rhs)); } template inline SPROUT_CONSTEXPR sprout::folder operator,(T&& lhs, sprout::folder_forwarder const& rhs) { return sprout::folder(rhs.func(), SPROUT_FORWARD(T, lhs)); } template inline SPROUT_CONSTEXPR sprout::folder&& operator,(sprout::folder&& lhs, U&& rhs) { return sprout::move(lhs.left(SPROUT_FORWARD(U, rhs))); } template inline SPROUT_CONSTEXPR sprout::folder&& operator,(U&& lhs, sprout::folder&& rhs) { return sprout::move(rhs.right(SPROUT_FORWARD(U, lhs))); } template inline SPROUT_CONSTEXPR sprout::folder_forwarder fold_by(BinaryOperation const& binary_op) { return sprout::folder_forwarder(binary_op); } template inline SPROUT_CONSTEXPR sprout::folder fold_by(BinaryOperation const& binary_op, T&& init) { return sprout::folder(binary_op, SPROUT_FORWARD(T, init)); } } // namespace sprout #endif // #ifndef SPROUT_UTILITY_FOLD_HPP