/* * Copyright (c) 2018 Jaroslav Jindrak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBCPP_BITS_FUNCTIONAL_ARITHMETIC_OPERATIONS #define LIBCPP_BITS_FUNCTIONAL_ARITHMETIC_OPERATIONS #include <__bits/utility/forward_move.hpp> #include namespace std { /** * 20.9.5, arithmetic operations: */ template struct plus { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs + rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct minus { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs - rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct multiplies { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs * rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct divides { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs / rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct modulus { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs % rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct negate { constexpr T operator()(const T& x) const { return -x; } using argument_type = T; using result_type = T; }; namespace aux { /** * Used by some functions like std::set::find to determine * whether a functor is transparent. */ struct transparent_t; template struct is_transparent: false_type { /* DUMMY BODY */ }; template struct is_transparent> : true_type { /* DUMMY BODY */ }; template inline constexpr bool is_transparent_v = is_transparent::value; } template<> struct plus { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) + forward(rhs)) { return forward(lhs) + forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct minus { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) - forward(rhs)) { return forward(lhs) - forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct multiplies { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) * forward(rhs)) { return forward(lhs) * forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct divides { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) / forward(rhs)) { return forward(lhs) / forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct modulus { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) % forward(rhs)) { return forward(lhs) % forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct negate { template constexpr auto operator()(T&& x) const -> decltype(-forward(x)) { return -forward(x); } using is_transparent = aux::transparent_t; }; /** * 20.9.6, comparisons: */ template struct equal_to { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template struct not_equal_to { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs != rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template struct greater { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs > rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template struct less { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template struct greater_equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs >= rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template struct less_equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs <= rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template<> struct equal_to { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) == forward(rhs)) { return forward(lhs) == forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct not_equal_to { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) != forward(rhs)) { return forward(lhs) != forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct greater { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) > forward(rhs)) { return forward(lhs) > forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct less { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) < forward(rhs)) { return forward(lhs) < forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct greater_equal { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) >= forward(rhs)) { return forward(lhs) >= forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct less_equal { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) <= forward(rhs)) { return forward(lhs) <= forward(rhs); } using is_transparent = aux::transparent_t; }; /** * 20.9.7, logical operations: */ template struct logical_and { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs && rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template struct logical_or { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs || rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = bool; }; template struct logical_not { constexpr bool operator()(const T& x) const { return !x; } using argument_type = T; using result_type = bool; }; template<> struct logical_and { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) && forward(rhs)) { return forward(lhs) && forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct logical_or { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) || forward(rhs)) { return forward(lhs) || forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct logical_not { template constexpr auto operator()(T&& x) const -> decltype(!forward(x)) { return !forward(x); } using is_transparent = aux::transparent_t; }; /** * 20.9.8, bitwise operations: */ template struct bit_and { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs & rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct bit_or { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs | rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct bit_xor { constexpr T operator()(const T& lhs, const T& rhs) const { return lhs ^ rhs; } using first_argument_type = T; using second_argument_type = T; using result_type = T; }; template struct bit_not { constexpr bool operator()(const T& x) const { return ~x; } using argument_type = T; using result_type = T; }; template<> struct bit_and { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) & forward(rhs)) { return forward(lhs) & forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct bit_or { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) | forward(rhs)) { return forward(lhs) | forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct bit_xor { template constexpr auto operator()(T&& lhs, U&& rhs) const -> decltype(forward(lhs) ^ forward(rhs)) { return forward(lhs) ^ forward(rhs); } using is_transparent = aux::transparent_t; }; template<> struct bit_not { template constexpr auto operator()(T&& x) const -> decltype(~forward(x)) { return ~forward(x); } using is_transparent = aux::transparent_t; }; /** * 20.9.9, negators: */ template class unary_negate { public: using result_type = bool; using argument_type = typename Predicate::argument_type; constexpr explicit unary_negate(const Predicate& pred) : pred_{pred} { /* DUMMY BODY */ } constexpr result_type operator()(const argument_type& arg) { return !pred_(arg); } private: Predicate pred_; }; template constexpr unary_negate not1(const Predicate& pred) { return unary_negate{pred}; } template class binary_negate { public: using result_type = bool; using first_argument_type = typename Predicate::first_argument_type; using second_argument_type = typename Predicate::second_argument_type; constexpr explicit binary_negate(const Predicate& pred) : pred_{pred} { /* DUMMY BODY */ } constexpr result_type operator()(const first_argument_type& arg1, const second_argument_type& arg2) { return !pred_(arg1, arg2); } private: Predicate pred_; }; template constexpr binary_negate not2(const Predicate& pred); } #endif