/* * Copyright 2020-present ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.1 */ #pragma once #include #include namespace utils { // Note: do not use directly, use utils::tagged_integer instead. // The reason this double-tagged template exist // is to distinguish between utils::tagged_integer // and raft::internal::tagged_uint64 that have incompatible // idl types and therefore must not be convertible to each other. template class tagged_tagged_integer { public: using value_type = ValueType; private: value_type _value; public: tagged_tagged_integer() noexcept : _value(0) {} explicit tagged_tagged_integer(value_type v) noexcept : _value(v) {} tagged_tagged_integer& operator=(value_type v) noexcept { _value = v; return *this; } value_type value() const noexcept { return _value; } explicit operator bool() const { return _value != 0; } auto operator<=>(const tagged_tagged_integer& o) const = default; tagged_tagged_integer& operator++() noexcept { ++_value; return *this; } tagged_tagged_integer& operator--() noexcept { --_value; return *this; } tagged_tagged_integer operator++(int) noexcept { auto ret = *this; ++_value; return ret; } tagged_tagged_integer operator--(int) noexcept { auto ret = *this; --_value; return ret; } tagged_tagged_integer operator+(const tagged_tagged_integer& o) const { return tagged_tagged_integer(_value + o._value); } tagged_tagged_integer operator-(const tagged_tagged_integer& o) const { return tagged_tagged_integer(_value - o._value); } tagged_tagged_integer& operator+=(const tagged_tagged_integer& o) { _value += o._value; return *this; } tagged_tagged_integer& operator-=(const tagged_tagged_integer& o) { _value -= o._value; return *this; } }; template using tagged_integer = tagged_tagged_integer; } // namespace utils template struct fmt::formatter> { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } auto format(const utils::tagged_tagged_integer& x, fmt::format_context& ctx) const { return fmt::format_to(ctx.out(), "{}", x.value()); } }; namespace std { template struct hash> { size_t operator()(const utils::tagged_tagged_integer& x) const noexcept { return hash{}(x.value()); } }; template [[maybe_unused]] ostream& operator<<(ostream& s, const utils::tagged_tagged_integer& x) { return s << x.value(); } template struct numeric_limits> : public numeric_limits { using tagged_tagged_integer_t = utils::tagged_tagged_integer; using value_limits = numeric_limits; static_assert(numeric_limits::is_specialized && numeric_limits::is_bounded); static constexpr tagged_tagged_integer_t min() { return tagged_tagged_integer_t(value_limits::min()); } static constexpr tagged_tagged_integer_t max() { return tagged_tagged_integer_t(value_limits::max()); } }; } // namespace std