IsCallable.hpp
1 // 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 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) noexcept
53  -> decltype(std::declval<T>()(std::declval<Args>()...), std::true_type());
54 
55  template <typename, typename...>
56  static auto test_callable(...) noexcept -> std::false_type;
57  /// \endcond
58 
59  public:
60  /// `true` if callable, `false` otherwise
61  static constexpr bool value = decltype(test_callable<TT, TArgs...>(0))::value;
62  /// `std::true_type` if callable, `std::false_type` otherwise
64 };
65 /// \see is_callable
66 template <typename T, typename... Args>
67 constexpr bool is_callable_v = is_callable<T, Args...>::value;
68 
69 /// \see is_callable
70 template <typename T, typename... Args>
71 using is_callable_t = typename is_callable<T, Args...>::type;
72 // @}
73 } // namespace tt
tt::is_callable_t
typename is_callable< T, Args... >::type is_callable_t
Definition: IsCallable.hpp:71
std::true_type
tt::is_callable::value
static constexpr bool value
true if callable, false otherwise
Definition: IsCallable.hpp:61
tt::is_callable_v
constexpr bool is_callable_v
Definition: IsCallable.hpp:67
tt
Definition: TensorExpression.hpp:121
tt::is_callable
Check if a type T is callable, i.e. T(Args...) is evaluable.
Definition: IsCallable.hpp:42
type_traits