diff options
Diffstat (limited to 'lib/util.h')
-rw-r--r-- | lib/util.h | 292 |
1 files changed, 148 insertions, 144 deletions
@@ -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 |