File indexing completed on 2024-05-19 05:33:32
0001 /* 0002 SPDX-FileCopyrightText: 2018 Ivan Čukić <ivan.cukic(at)kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #ifndef VOY_TRAITS_H 0008 #define VOY_TRAITS_H 0009 0010 // STL 0011 #include <type_traits> 0012 0013 // Some meta-programming utility functions and meta-functions, 0014 // including the detection idiom - the poor man's concepts 0015 0016 #define voy_concept inline constexpr bool 0017 0018 #define voy_require(Condition) typename std::enable_if_t<Condition, int> = 0 0019 0020 #define voy_assert_value_type(Type) \ 0021 static_assert(std::is_same_v<Type, ::voy::traits::remove_cvref_t<Type>>, \ 0022 "This needs to be a value type") 0023 0024 namespace voy::traits { 0025 0026 // Meta-function to force the compiler to print out the exact type passed 0027 // to it by creating a compilation error because the type is not implemented 0028 template <typename... Types> 0029 struct print_types; 0030 0031 // Meta-function that always returns false. It is useful for marking a 0032 // particular if-constexpr branch to be erroneous 0033 template <typename T> 0034 voy_concept always_fail = false; 0035 0036 #define voy_fail(Type, Msg) static_assert(::voy::traits::always_fail<Type>, Msg) 0037 0038 0039 // C++20 Stuff 0040 0041 // Meta-function which strips out the reference and cv qualifiers from the type 0042 template <typename T> 0043 using remove_cvref_t = std::remove_reference_t<std::remove_cv_t<T>>; 0044 0045 0046 // The detection idiom -- static introspection made easy 0047 0048 struct nonesuch { 0049 nonesuch() = delete; 0050 ~nonesuch() = delete; 0051 nonesuch(const nonesuch&) = delete; 0052 nonesuch& operator=(const nonesuch&) = delete; 0053 }; 0054 0055 namespace detail { 0056 template < typename Default 0057 , typename Void 0058 , template <typename...> typename Operation 0059 , typename... Args 0060 > 0061 struct detector { 0062 using value_t = std::false_type; 0063 using type = Default; 0064 }; 0065 0066 template < typename Default 0067 , template <typename...> typename Operation 0068 , typename... Args 0069 > 0070 struct detector < Default 0071 , std::void_t<Operation<Args...>> 0072 , Operation 0073 , Args... 0074 > { 0075 using value_t = std::true_type; 0076 using type = Operation<Args...>; 0077 }; 0078 } // namespace detail 0079 0080 0081 template < template <typename...> typename Operation 0082 , typename... Args 0083 > 0084 using is_detected = typename detail::detector < nonesuch 0085 , void 0086 , Operation 0087 , Args... 0088 >::value_t; 0089 0090 0091 template < template <typename...> typename Operation 0092 , typename... Args 0093 > 0094 voy_concept is_detected_v = is_detected<Operation, Args...>::value; 0095 0096 0097 template < template <typename...> typename Operation 0098 , typename... Args 0099 > 0100 using is_detected_t = typename is_detected<Operation, Args...>::type; 0101 0102 0103 template < template <typename...> typename Operation 0104 , typename... Args 0105 > 0106 using detected_t = typename detail::detector < nonesuch 0107 , void 0108 , Operation 0109 , Args...>::type; 0110 0111 0112 } // namespace voy::traits 0113 0114 #endif // include guard 0115