aboutsummaryrefslogtreecommitdiff
path: root/lib/util.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util.h')
-rw-r--r--lib/util.h292
1 files changed, 148 insertions, 144 deletions
diff --git a/lib/util.h b/lib/util.h
index f7f646da..fbcafc0d 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -13,7 +13,7 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
@@ -21,8 +21,8 @@
#include <QtCore/QLatin1String>
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
-#include <QtCore/QMetaEnum>
#include <QtCore/QDebug>
+#include <QtCore/QMetaEnum>
#endif
#include <functional>
@@ -39,41 +39,43 @@
#endif
// Along the lines of Q_DISABLE_COPY
-#define DISABLE_MOVE(_ClassName) \
- _ClassName(_ClassName&&) Q_DECL_EQ_DELETE; \
+#define DISABLE_MOVE(_ClassName) \
+ _ClassName(_ClassName&&) Q_DECL_EQ_DELETE; \
_ClassName& operator=(_ClassName&&) Q_DECL_EQ_DELETE;
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
// Copy-pasted from Qt 5.10
template <typename T>
-Q_DECL_CONSTEXPR typename std::add_const<T>::type &qAsConst(T &t) Q_DECL_NOTHROW { return t; }
+Q_DECL_CONSTEXPR typename std::add_const<T>::type& qAsConst(T& t) Q_DECL_NOTHROW
+{
+ return t;
+}
// prevent rvalue arguments:
-template <typename T>
-static void qAsConst(const T &&) Q_DECL_EQ_DELETE;
+template <typename T> static void qAsConst(const T&&) Q_DECL_EQ_DELETE;
#endif
// MSVC 2015 and older GCC's don't handle initialisation from initializer lists
// right in the absense of a constructor; MSVC 2015, notably, fails with
// "error C2440: 'return': cannot convert from 'initializer list' to '<type>'"
-#if (defined(_MSC_VER) && _MSC_VER < 1910) || \
- (defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4)
-# define BROKEN_INITIALIZER_LISTS
+#if (defined(_MSC_VER) && _MSC_VER < 1910) \
+ || (defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4)
+#define BROKEN_INITIALIZER_LISTS
#endif
-namespace QMatrixClient
-{
+namespace QMatrixClient {
// The below enables pretty-printing of enums in logs
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
#define REGISTER_ENUM(EnumName) Q_ENUM(EnumName)
#else
// Thanks to Olivier for spelling it and for making Q_ENUM to replace it:
// https://woboq.com/blog/q_enum.html
-#define REGISTER_ENUM(EnumName) \
- Q_ENUMS(EnumName) \
- friend QDebug operator<<(QDebug dbg, EnumName val) \
- { \
- static int enumIdx = staticMetaObject.indexOfEnumerator(#EnumName); \
- return dbg << Event::staticMetaObject.enumerator(enumIdx).valueToKey(int(val)); \
+#define REGISTER_ENUM(EnumName) \
+ Q_ENUMS(EnumName) \
+ friend QDebug operator<<(QDebug dbg, EnumName val) \
+ { \
+ static int enumIdx = staticMetaObject.indexOfEnumerator(#EnumName); \
+ return dbg << Event::staticMetaObject.enumerator(enumIdx).valueToKey( \
+ int(val)); \
}
#endif
@@ -84,97 +86,101 @@ namespace QMatrixClient
return std::unique_ptr<T1>(static_cast<T1*>(p.release()));
}
- struct NoneTag {};
+ struct NoneTag {
+ };
constexpr NoneTag none {};
/** A crude substitute for `optional` while we're not C++17
*
* Only works with default-constructible types.
*/
- template <typename T>
- class Omittable
+ template <typename T> class Omittable
{
- static_assert(!std::is_reference<T>::value,
- "You cannot make an Omittable<> with a reference type");
+ static_assert(!std::is_reference<T>::value,
+ "You cannot make an Omittable<> with a reference type");
+
public:
- using value_type = std::decay_t<T>;
-
- explicit Omittable() : Omittable(none) { }
- Omittable(NoneTag) : _value(value_type()), _omitted(true) { }
- Omittable(const value_type& val) : _value(val) { }
- Omittable(value_type&& val) : _value(std::move(val)) { }
- Omittable<T>& operator=(const value_type& val)
- {
- _value = val;
- _omitted = false;
- return *this;
- }
- Omittable<T>& operator=(value_type&& val)
- {
- // For some reason GCC complains about -Wmaybe-uninitialized
- // in the context of using Omittable<bool> with converters.h;
- // though the logic looks very much benign (GCC bug???)
- _value = std::move(val);
- _omitted = false;
- return *this;
- }
-
- bool operator==(const value_type& rhs) const
- {
- return !omitted() && value() == rhs;
- }
- friend bool operator==(const value_type& lhs,
- const Omittable<value_type>& rhs)
- {
- return rhs == lhs;
- }
- bool operator!=(const value_type& rhs) const
- {
- return !operator==(rhs);
- }
- friend bool operator!=(const value_type& lhs,
- const Omittable<value_type>& rhs)
- {
- return !(rhs == lhs);
- }
-
- bool omitted() const { return _omitted; }
- const value_type& value() const
- {
- Q_ASSERT(!_omitted);
- return _value;
- }
- value_type& editValue()
- {
- _omitted = false;
- return _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
- template <typename T1>
- auto merge(const Omittable<T1>& other)
+ using value_type = std::decay_t<T>;
+
+ explicit Omittable() : Omittable(none) {}
+ Omittable(NoneTag) : _value(value_type()), _omitted(true) {}
+ Omittable(const value_type& val) : _value(val) {}
+ Omittable(value_type&& val) : _value(std::move(val)) {}
+ Omittable<T>& operator=(const value_type& val)
+ {
+ _value = val;
+ _omitted = false;
+ return *this;
+ }
+ Omittable<T>& operator=(value_type&& val)
+ {
+ // For some reason GCC complains about -Wmaybe-uninitialized
+ // in the context of using Omittable<bool> with converters.h;
+ // though the logic looks very much benign (GCC bug???)
+ _value = std::move(val);
+ _omitted = false;
+ return *this;
+ }
+
+ bool operator==(const value_type& rhs) const
+ {
+ return !omitted() && value() == rhs;
+ }
+ friend bool operator==(const value_type& lhs,
+ const Omittable<value_type>& rhs)
+ {
+ return rhs == lhs;
+ }
+ bool operator!=(const value_type& rhs) const
+ {
+ return !operator==(rhs);
+ }
+ friend bool operator!=(const value_type& lhs,
+ const Omittable<value_type>& rhs)
+ {
+ return !(rhs == lhs);
+ }
+
+ bool omitted() const { return _omitted; }
+ const value_type& value() const
+ {
+ Q_ASSERT(!_omitted);
+ return _value;
+ }
+ value_type& editValue()
+ {
+ _omitted = false;
+ return _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
+ template <typename T1>
+ auto merge(const Omittable<T1>& other)
-> std::enable_if_t<std::is_convertible<T1, T>::value, bool>
- {
- if (other.omitted() ||
- (!_omitted && _value == other.value()))
- return false;
- _omitted = false;
- _value = other.value();
- return true;
- }
- value_type&& release() { _omitted = true; return std::move(_value); }
-
- const value_type* operator->() const & { return &value(); }
- value_type* operator->() & { return &editValue(); }
- const value_type& operator*() const & { return value(); }
- value_type& operator*() & { return editValue(); }
+ {
+ if (other.omitted() || (!_omitted && _value == other.value()))
+ return false;
+ _omitted = false;
+ _value = other.value();
+ return true;
+ }
+ value_type&& release()
+ {
+ _omitted = true;
+ return std::move(_value);
+ }
+
+ const value_type* operator->() const& { return &value(); }
+ value_type* operator->() & { return &editValue(); }
+ const value_type& operator*() const& { return value(); }
+ value_type& operator*() & { return editValue(); }
private:
- T _value;
- bool _omitted = false;
+ T _value;
+ bool _omitted = false;
};
namespace _impl {
@@ -184,15 +190,16 @@ namespace QMatrixClient
/** Determine traits of an arbitrary function/lambda/functor
* Doesn't work with generic lambdas and function objects that have
* operator() overloaded.
- * \sa https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda#7943765
+ * \sa
+ * https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda#7943765
*/
template <typename T>
- struct function_traits : public _impl::fn_traits<void, T> {};
+ struct function_traits : public _impl::fn_traits<void, T> {
+ };
// Specialisation for a function
template <typename ReturnT, typename... ArgTs>
- struct function_traits<ReturnT(ArgTs...)>
- {
+ struct function_traits<ReturnT(ArgTs...)> {
static constexpr auto is_callable = true;
using return_type = ReturnT;
using arg_types = std::tuple<ArgTs...>;
@@ -201,39 +208,37 @@ namespace QMatrixClient
};
namespace _impl {
- template <typename AlwaysVoid, typename T>
- struct fn_traits
- {
+ template <typename AlwaysVoid, typename T> struct fn_traits {
static constexpr auto is_callable = false;
};
template <typename T>
struct fn_traits<decltype(void(&T::operator())), T>
- : public fn_traits<void, decltype(&T::operator())>
- { }; // A generic function object that has (non-overloaded) operator()
+ : public fn_traits<void, decltype(&T::operator())> {
+ }; // A generic function object that has (non-overloaded) operator()
// Specialisation for a member function
template <typename ReturnT, typename ClassT, typename... ArgTs>
- struct fn_traits<void, ReturnT(ClassT::*)(ArgTs...)>
- : function_traits<ReturnT(ArgTs...)>
- { };
+ struct fn_traits<void, ReturnT (ClassT::*)(ArgTs...)>
+ : function_traits<ReturnT(ArgTs...)> {
+ };
// Specialisation for a const member function
template <typename ReturnT, typename ClassT, typename... ArgTs>
- struct fn_traits<void, ReturnT(ClassT::*)(ArgTs...) const>
- : function_traits<ReturnT(ArgTs...)>
- { };
- } // namespace _impl
+ struct fn_traits<void, ReturnT (ClassT::*)(ArgTs...) const>
+ : function_traits<ReturnT(ArgTs...)> {
+ };
+ } // namespace _impl
template <typename FnT>
using fn_return_t = typename function_traits<FnT>::return_type;
template <typename FnT, int ArgN = 0>
using fn_arg_t =
- std::tuple_element_t<ArgN, typename function_traits<FnT>::arg_types>;
+ std::tuple_element_t<ArgN,
+ typename function_traits<FnT>::arg_types>;
- template <typename R, typename FnT>
- constexpr bool returns()
+ template <typename R, typename FnT> constexpr bool returns()
{
return std::is_same<fn_return_t<FnT>, R>::value;
}
@@ -251,31 +256,31 @@ namespace QMatrixClient
* This is a very basic range type over a container with iterators that
* are at least ForwardIterators. Inspired by Ranges TS.
*/
- template <typename ArrayT>
- class Range
+ template <typename ArrayT> class Range
{
- // Looking forward for Ranges TS to produce something (in C++23?..)
- using iterator = typename ArrayT::iterator;
- using const_iterator = typename ArrayT::const_iterator;
- using size_type = typename ArrayT::size_type;
+ // Looking forward for Ranges TS to produce something (in C++23?..)
+ using iterator = typename ArrayT::iterator;
+ using const_iterator = typename ArrayT::const_iterator;
+ using size_type = typename ArrayT::size_type;
+
public:
- Range(ArrayT& arr) : from(std::begin(arr)), to(std::end(arr)) { }
- Range(iterator from, iterator to) : from(from), to(to) { }
-
- size_type size() const
- {
- Q_ASSERT(std::distance(from, to) >= 0);
- return size_type(std::distance(from, to));
- }
- bool empty() const { return from == to; }
- const_iterator begin() const { return from; }
- const_iterator end() const { return to; }
- iterator begin() { return from; }
- iterator end() { return to; }
+ Range(ArrayT& arr) : from(std::begin(arr)), to(std::end(arr)) {}
+ Range(iterator from, iterator to) : from(from), to(to) {}
+
+ size_type size() const
+ {
+ Q_ASSERT(std::distance(from, to) >= 0);
+ return size_type(std::distance(from, to));
+ }
+ bool empty() const { return from == to; }
+ const_iterator begin() const { return from; }
+ const_iterator end() const { return to; }
+ iterator begin() { return from; }
+ iterator end() { return to; }
private:
- iterator from;
- iterator to;
+ iterator from;
+ iterator to;
};
/** A replica of std::find_first_of that returns a pair of iterators
@@ -283,10 +288,10 @@ namespace QMatrixClient
* Convenient for cases when you need to know which particular "first of"
* [sFirst, sLast) has been found in [first, last).
*/
- template<typename InputIt, typename ForwardIt, typename Pred>
- inline std::pair<InputIt, ForwardIt> findFirstOf(
- InputIt first, InputIt last, ForwardIt sFirst, ForwardIt sLast,
- Pred pred)
+ template <typename InputIt, typename ForwardIt, typename Pred>
+ inline std::pair<InputIt, ForwardIt>
+ findFirstOf(InputIt first, InputIt last, ForwardIt sFirst, ForwardIt sLast,
+ Pred pred)
{
for (; first != last; ++first)
for (auto it = sFirst; it != sLast; ++it)
@@ -306,5 +311,4 @@ namespace QMatrixClient
* \param dir path to cache directory relative to the standard cache path
*/
QString cacheLocation(const QString& dirName);
-} // namespace QMatrixClient
-
+} // namespace QMatrixClient