From b99184792d7fc6ea0cf007f8df4aa6539b19ed19 Mon Sep 17 00:00:00 2001 From: Hans Dembinski Date: Tue, 11 Jun 2019 22:33:53 +0200 Subject: [PATCH] comparisons simplified --- include/boost/histogram/unlimited_storage.hpp | 122 ++++++------------ 1 file changed, 39 insertions(+), 83 deletions(-) diff --git a/include/boost/histogram/unlimited_storage.hpp b/include/boost/histogram/unlimited_storage.hpp index 0721eea6..bce10986 100644 --- a/include/boost/histogram/unlimited_storage.hpp +++ b/include/boost/histogram/unlimited_storage.hpp @@ -32,8 +32,16 @@ namespace boost { namespace histogram { namespace detail { -template ::value>> -struct requires_arithmetic {}; +template +struct is_large_int : std::false_type {}; + +template +struct is_large_int> : std::true_type {}; + +template +using if_arithmetic_or_large_int = + std::enable_if_t<(std::is_arithmetic::value || is_large_int::value), + ReturnType>; template using next_type = mp11::mp_at_c::value + 1)>; @@ -250,7 +258,7 @@ public: /// implementation detail class const_reference - : detail::partially_ordered { + : detail::partially_ordered { public: const_reference(buffer_type& b, std::size_t i) noexcept : bref_(b), idx_(i) { BOOST_ASSERT(idx_ < bref_.size); @@ -271,38 +279,22 @@ public: return apply_binary(o); } - bool operator<(const large_int& o) const noexcept { - return apply_binary(o); - } - - template - bool operator<(const U& o) const noexcept { - return apply_binary(o); - } - - bool operator>(const const_reference& rhs) const noexcept { - return apply_binary(rhs); - } - - bool operator>(const large_int& rhs) const noexcept { - return apply_binary(rhs); - } - - template - bool operator>(const U& o) const noexcept { - return apply_binary(o); - } - bool operator==(const const_reference& o) const noexcept { return apply_binary(o); } - bool operator==(const large_int& rhs) const noexcept { - return apply_binary(rhs); + template + detail::if_arithmetic_or_large_int operator<(const U& o) const noexcept { + return apply_binary(o); } template - bool operator==(const U& o) const noexcept { + detail::if_arithmetic_or_large_int operator>(const U& o) const noexcept { + return apply_binary(o); + } + + template + detail::if_arithmetic_or_large_int operator==(const U& o) const noexcept { return apply_binary(o); } @@ -327,8 +319,7 @@ public: /// implementation detail class reference : public const_reference, - public detail::partially_ordered { + public detail::partially_ordered { public: reference(buffer_type& b, std::size_t i) noexcept : const_reference(b, i) {} @@ -340,74 +331,44 @@ public: return operator=(static_cast(x)); } + // references do not rebind, assign through reference& operator=(const const_reference& x) { // safe for self-assignment, assigning matching type doesn't invalide buffer x.bref_.visit([this, ix = x.idx_](const auto* xp) { this->operator=(xp[ix]); }); return *this; } - template > - reference& operator=(const U& x) { + template + detail::if_arithmetic_or_large_int operator=(const U& x) { this->bref_.visit([this, &x](auto* p) { - p[this->idx_] = 0; // LCOV_EXCL_LINE gcc-8 optimizes this away even at -O0 - adder()(p, this->bref_, this->idx_, x); + // gcc-8 optimizes the expression `p[this->idx_] = 0` away even at -O0, + // so we merge it into the next line which is properly counted + adder()((p[this->idx_] = 0, p), this->bref_, this->idx_, x); }); return *this; } - reference& operator=(const large_int& x) { - this->bref_.visit([this, &x](auto* p) { - p[this->idx_] = 0; // LCOV_EXCL_LINE gcc-8 optimizes this away even at -O0 - adder()(p, this->bref_, this->idx_, x); - }); - return *this; - } - - bool operator<(const const_reference& o) const noexcept { - return const_reference::operator<(o); - } - - bool operator>(const const_reference& o) const noexcept { - return const_reference::operator>(o); - } - - bool operator==(const const_reference& o) const noexcept { - return const_reference::operator==(o); - } - bool operator<(const reference& o) const noexcept { - return const_reference::operator<(static_cast(o)); - } - - bool operator==(const reference& o) const noexcept { - return const_reference::operator==(static_cast(o)); - } - - bool operator<(const large_int& o) const noexcept { return const_reference::operator<(o); } - bool operator>(const large_int& o) const noexcept { - return const_reference::operator>(o); - } - - bool operator==(const large_int& o) const noexcept { + bool operator==(const reference& o) const noexcept { return const_reference::operator==(o); } - template > - bool operator<(const U& o) const noexcept { - return static_cast(*this) < o; + template + detail::if_arithmetic_or_large_int operator<(const U& o) const noexcept { + return const_reference::operator<(o); } - template > - bool operator>(const U& o) const noexcept { - return static_cast(*this) > o; + template + detail::if_arithmetic_or_large_int operator>(const U& o) const noexcept { + return const_reference::operator>(o); } - template > - bool operator==(const U& o) const noexcept { - return static_cast(*this) == o; + template + detail::if_arithmetic_or_large_int operator==(const U& o) const noexcept { + return const_reference::operator==(o); } reference& operator+=(const const_reference& x) { @@ -415,13 +376,8 @@ public: return *this; } - template > - reference& operator+=(const U& x) { - this->bref_.visit(adder(), this->bref_, this->idx_, x); - return *this; - } - - reference& operator+=(const large_int& x) { + template + detail::if_arithmetic_or_large_int operator+=(const U& x) { this->bref_.visit(adder(), this->bref_, this->idx_, x); return *this; }