diff options
author | Alexey Rusakov <Kitsune-Ral@users.sf.net> | 2021-07-24 20:56:50 +0200 |
---|---|---|
committer | Alexey Rusakov <Kitsune-Ral@users.sf.net> | 2021-07-24 20:56:50 +0200 |
commit | cddf3c6a2ab7481e5816ca7632b9f919efa0ac40 (patch) | |
tree | 036840ccd377d58717c2a6552652708c91d293b1 /lib/util.h | |
parent | f340d73ae5dac0d0cfee732aabbd5222c7be16dd (diff) | |
download | libquotient-cddf3c6a2ab7481e5816ca7632b9f919efa0ac40.tar.gz libquotient-cddf3c6a2ab7481e5816ca7632b9f919efa0ac40.zip |
Wrap SyncRoomData counters into Omittables
Also: introduce a merge(T1&, const Omittable<T2>&) that does pretty much
the same as Omittable<T1>::merge(const Omittable<T2>&) except it works
on non-omittables as the left/first operand.
The change removes the need for a clumsy -2 fallback in unreadCount,
and makes the logic loading those counters cleaner along the way.
Diffstat (limited to 'lib/util.h')
-rw-r--r-- | lib/util.h | 49 |
1 files changed, 42 insertions, 7 deletions
@@ -30,6 +30,13 @@ struct HashQ { template <typename KeyT, typename ValT> using UnorderedMap = std::unordered_map<KeyT, ValT, HashQ<KeyT>>; +namespace _impl { + template <typename TT> + constexpr inline auto IsOmittableValue = false; + template <typename TT> + constexpr inline auto IsOmittable = IsOmittableValue<std::decay_t<TT>>; +} + constexpr auto none = std::nullopt; /** `std::optional` with tweaks @@ -107,18 +114,18 @@ public: return !this->has_value(); } - /// Merge the value from another Omittable - /// \return true if \p other is not omitted and the value of - /// the current Omittable was different (or omitted); - /// in other words, if the current Omittable has changed; - /// false otherwise + //! Merge the value from another Omittable + //! \return true if \p other is not omitted and the value of + //! the current Omittable was different (or omitted), + //! in other words, if the current Omittable has changed; + //! false otherwise template <typename T1> auto merge(const Omittable<T1>& other) - -> std::enable_if_t<std::is_convertible<T1, T>::value, bool> + -> std::enable_if_t<std::is_convertible_v<T1, T>, bool> { if (!other || (this->has_value() && **this == *other)) return false; - *this = other; + emplace(*other); return true; } @@ -133,6 +140,34 @@ public: }; namespace _impl { + template <typename T> + constexpr inline auto IsOmittableValue<Omittable<T>> = true; +} + +template <typename T1, typename T2> +inline auto merge(Omittable<T1>& lhs, T2&& rhs) +{ + return lhs.merge(std::forward<T2>(rhs)); +} + +//! \brief Merge the value from an Omittable +//! This is an adaptation of Omittable::merge() to the case when the value +//! on the left hand side is not an Omittable. +//! \return true if \p rhs is not omitted and the \p lhs value was different, +//! in other words, if \p lhs has changed; +//! false otherwise +template <typename T1, typename T2> +inline auto merge(T1& lhs, const Omittable<T2>& rhs) + -> std::enable_if_t<!_impl::IsOmittable<T1> + && std::is_convertible_v<T2, T1>, bool> +{ + if (!rhs || lhs == *rhs) + return false; + lhs = *rhs; + return true; +} + +namespace _impl { template <typename AlwaysVoid, typename> struct fn_traits {}; } |