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 : namespace tt { 9 : /// @{ 10 : /// \ingroup TypeTraitsGroup 11 : /// \brief Check if a type `T` is callable, i.e. `T(Args...)` is evaluable. 12 : /// 13 : /// \details 14 : /// Inherits from std::true_type if `TT` has the call operator, operator() 15 : /// defined with arguments `TArgs...`, otherwise inherits from std::false_type. 16 : /// 17 : /// \usage 18 : /// For any type `TT` and types `TArgs_i`, 19 : /// \code 20 : /// using result = tt::is_callable<TT, TArgs_0, TArgs_1, TArgs_2>; 21 : /// \endcode 22 : /// 23 : /// \metareturns 24 : /// std::bool_constant 25 : /// 26 : /// \semantics 27 : /// If the type `TT` defines operator() with arguments `TArgs...`, then 28 : /// \code 29 : /// typename result::type = std::true_type; 30 : /// \endcode 31 : /// otherwise 32 : /// \code 33 : /// typename result::type = std::false_type; 34 : /// \endcode 35 : /// 36 : /// \example 37 : /// \snippet Test_IsCallable.cpp is_callable_example 38 : /// \see std::is_callable 39 : /// \tparam TT the class to check 40 : /// \tparam TArgs the args passed to operator() 41 : template <typename TT, typename... TArgs> 42 1 : class is_callable { 43 : // The reason we have private before public here is that we have static member 44 : // functions and since this is meant to be a super lightweight helper class 45 : // it's better to break convention than increase code size. 46 : private: 47 : /// \cond 48 : // We pass an int here to disambiguate the two possible templates and have the 49 : // compiler prefer the first one. If it cannot be used because there's no 50 : // call operator, then it uses the second one. 51 : template <typename T, typename... Args> 52 : static auto test_callable(int) 53 : -> decltype(std::declval<T>()(std::declval<Args>()...), std::true_type()); 54 : 55 : template <typename, typename...> 56 : static auto test_callable(...) -> std::false_type; 57 : /// \endcond 58 : 59 : public: 60 : /// `true` if callable, `false` otherwise 61 1 : static constexpr bool value = decltype(test_callable<TT, TArgs...>(0))::value; 62 : /// `std::true_type` if callable, `std::false_type` otherwise 63 1 : using type = std::integral_constant<bool, value>; 64 : }; 65 : /// \see is_callable 66 : template <typename T, typename... Args> 67 1 : constexpr bool is_callable_v = is_callable<T, Args...>::value; 68 : 69 : /// \see is_callable 70 : template <typename T, typename... Args> 71 1 : using is_callable_t = typename is_callable<T, Args...>::type; 72 : /// @} 73 : } // namespace tt