Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <type_traits> 7 : 8 : /// @{ 9 : /*! 10 : * \ingroup TypeTraitsGroup 11 : * \brief Generate a type trait to check if a class has a member function that 12 : * can be invoked with arguments of type `TArgs...` 13 : * 14 : * The usage of the type trait is identical to the usage of the 15 : * `tt::is_callable` type trait. The name of the type trait is 16 : * `is_METHOD_NAME_callable` and is not placed in 17 : * the `tt` namespace. To avoid collisions it is highly recommended that type 18 : * traits generated with this macro are generated into `_detail` namespaces. 19 : * This will reduce redefinition compilation errors. 20 : * 21 : * Note that variable templates with `_r` and `_t` suffixes that follow the 22 : * standard library's naming convention are also generated. To generate 23 : * corresponding `_v` metafunctions, call `CREATE_IS_CALLABLE` first and then 24 : * `CREATE_IS_CALLABLE_V` and/or `CREATE_IS_CALLABLE_R_V`. 25 : * 26 : * \example 27 : * \snippet Test_CreateIsCallable.cpp CREATE_IS_CALLABLE_EXAMPLE 28 : * 29 : * \see tt::is_callable 30 : */ 31 1 : #define CREATE_IS_CALLABLE(METHOD_NAME) \ 32 : struct AnyReturnType##METHOD_NAME {}; \ 33 : \ 34 : template <typename ReturnType, typename TT, typename... TArgs> \ 35 : class is_##METHOD_NAME##_callable_r { \ 36 : private: \ 37 : struct NotCallable {}; \ 38 : template <typename T, typename... Args> \ 39 : static auto test_callable(int) \ 40 : -> decltype(std::declval<T>().METHOD_NAME(std::declval<Args>()...)); \ 41 : template <typename, typename...> \ 42 : static auto test_callable(...) -> NotCallable; \ 43 : \ 44 : public: \ 45 : static constexpr bool value = \ 46 : (std::is_same_v<ReturnType, AnyReturnType##METHOD_NAME> and \ 47 : not std::is_same_v<decltype(test_callable<TT, TArgs...>(0)), \ 48 : NotCallable>) or \ 49 : std::is_same_v<decltype(test_callable<TT, TArgs...>(0)), ReturnType>; \ 50 : using type = std::integral_constant<bool, value>; \ 51 : }; \ 52 : template <typename ReturnType, typename T, typename... Args> \ 53 : using is_##METHOD_NAME##_callable_r_t = \ 54 : typename is_##METHOD_NAME##_callable_r<ReturnType, T, Args...>::type; \ 55 : template <typename TT, typename... TArgs> \ 56 : using is_##METHOD_NAME##_callable = \ 57 : is_##METHOD_NAME##_callable_r<AnyReturnType##METHOD_NAME, TT, TArgs...>; \ 58 : template <typename TT, typename... TArgs> \ 59 : using is_##METHOD_NAME##_callable_t = \ 60 : is_##METHOD_NAME##_callable_r_t<AnyReturnType##METHOD_NAME, TT, \ 61 : TArgs...>; 62 : 63 : // Separate macros to avoid compiler warnings about unused variables 64 1 : #define CREATE_IS_CALLABLE_R_V(METHOD_NAME) \ 65 : template <typename ReturnType, typename T, typename... Args> \ 66 : constexpr bool is_##METHOD_NAME##_callable_r_v = \ 67 : is_##METHOD_NAME##_callable_r<ReturnType, T, Args...>::value; 68 1 : #define CREATE_IS_CALLABLE_V(METHOD_NAME) \ 69 : template <typename T, typename... Args> \ 70 : constexpr bool is_##METHOD_NAME##_callable_v = \ 71 : is_##METHOD_NAME##_callable<T, Args...>::value; 72 : /// @}