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 : /// @}
|