diff --git a/src/shared/aktraits.h b/src/shared/aktraits.h index 0393a4b28..2e6e2f817 100644 --- a/src/shared/aktraits.h +++ b/src/shared/aktraits.h @@ -1,163 +1,163 @@ /* Copyright (C) 2019 Daniel Vrátil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_AKTRAITS_H_ #define AKONADI_AKTRAITS_H_ #include #include namespace Akonadi { namespace AkTraits { namespace detail { /// Helpers from C++17 template using void_t = void; template struct conjunction : std::true_type {}; template struct conjunction : T {}; template struct conjunction : std::conditional_t, T> {}; /// Check for presence of member type template> struct hasMember { static constexpr bool value = false; }; template struct hasMember> : std::true_type {}; /// TODO: Use Boost TTI instead? #define DECLARE_HAS_METHOD_GENERIC_IMPL(name, fun, sign) \ template \ struct hasMethod_##name { \ public: \ template \ struct helperClass; \ \ using True = char; \ using False = struct { char dummy_[2]; }; \ \ template \ static True helper(helperClass*);\ template \ static False helper(...); \ public: \ static constexpr bool value = sizeof(helper(nullptr)) == sizeof(True); \ }; #define DECLARE_HAS_METHOD_GENERIC_CONST(fun, R, ...) \ DECLARE_HAS_METHOD_GENERIC_IMPL(fun##_const, fun, R(T::*)(__VA_ARGS__) const) #define DECLARE_HAS_METHOD_GENERIC(fun, R, ...) \ DECLARE_HAS_METHOD_GENERIC_IMPL(fun, fun, R(T::*)(__VA_ARGS__)) - DECLARE_HAS_METHOD_GENERIC_CONST(size, int) + DECLARE_HAS_METHOD_GENERIC_CONST(size, int, void) DECLARE_HAS_METHOD_GENERIC(push_back, void, const typename T::value_type &) DECLARE_HAS_METHOD_GENERIC(insert, typename T::iterator, const typename T::value_type &) DECLARE_HAS_METHOD_GENERIC(reserve, void, int) #define DECLARE_HAS_FUNCTION(name, fun) \ template \ struct has_##name { \ template \ struct helperClass; \ \ using True = char; \ using False = struct { char dummy_[2]; }; \ \ template \ static True helper(helperClass()))>*); \ template \ static False helper(...); \ public: \ static constexpr bool value = sizeof(helper(nullptr)) == sizeof(True); \ }; // For some obscure reason QVector::begin() actually has a default // argument, but QList::begin() does not, thus a regular hasMethod_* check // won't cut it here. Instead we check whether the container object can be // used with std::begin() and std::end() helpers. // Check for constness can be performed by passing "const T" to the type. DECLARE_HAS_FUNCTION(begin, std::begin) DECLARE_HAS_FUNCTION(end, std::end) /// This is a very incomplete set of Container named requirement, but I'm /// too lazy to implement all of them, but this should be good enough to match /// regular Qt containers and /not/ match arbitrary non-container types template struct isContainer : conjunction< std::is_constructible, hasMember, has_begin, has_begin, has_end, has_end, hasMethod_size_const > {}; /// Matches anything that is a container and has push_back() method. template struct isAppendable : conjunction< isContainer, hasMethod_push_back > {}; /// Matches anything that is a container and has insert() method. template struct isInsertable : conjunction< isContainer, hasMethod_insert > {}; /// Matches anything that is a container and has reserve() method. template struct isReservable : conjunction< isContainer, hasMethod_reserve > {}; } template constexpr bool isAppendable = detail::isAppendable::value; template constexpr bool isInsertable = detail::isInsertable::value; template constexpr bool isReservable = detail::isReservable::value; } } #define AK_PP_CAT_(X, Y) X ## Y #define AK_PP_CAT(X, Y) AK_PP_CAT_(X, Y) #define AK_REQUIRES(...) \ bool AK_PP_CAT(_ak_requires_, __LINE__) = false, \ std::enable_if_t< \ AK_PP_CAT(_ak_requires_, __LINE__) || (__VA_ARGS__) \ >* = nullptr #endif