aboutsummaryrefslogtreecommitdiff
path: root/lib/util.h
diff options
context:
space:
mode:
authorAlexey Rusakov <Kitsune-Ral@users.sf.net>2021-07-24 20:56:50 +0200
committerAlexey Rusakov <Kitsune-Ral@users.sf.net>2021-07-24 20:56:50 +0200
commitcddf3c6a2ab7481e5816ca7632b9f919efa0ac40 (patch)
tree036840ccd377d58717c2a6552652708c91d293b1 /lib/util.h
parentf340d73ae5dac0d0cfee732aabbd5222c7be16dd (diff)
downloadlibquotient-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.h49
1 files changed, 42 insertions, 7 deletions
diff --git a/lib/util.h b/lib/util.h
index 7f09de28..78fc9ab7 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -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 {};
}