fork(5) download
  1. #include <functional> // std::function, std::bind (for example)
  2. #include <iostream> // std::cout, std::endl, std::boolalpha (for example)
  3. #include <utility> // std::declval (for example)
  4. #include <type_traits> // std::remove_reference_t, std::true_type, std::false_type (for implementation)
  5.  
  6. // is_callable IMPLEMENTATION
  7.  
  8. template<typename T, typename U = void>
  9. struct is_callable
  10. {
  11. static bool const constexpr value = std::conditional_t<
  12. std::is_class<std::remove_reference_t<T>>::value,
  13. is_callable<std::remove_reference_t<T>, int>, std::false_type>::value;
  14. };
  15.  
  16. template<typename T, typename U, typename ...Args>
  17. struct is_callable<T(Args...), U> : std::true_type {};
  18. template<typename T, typename U, typename ...Args>
  19. struct is_callable<T(*)(Args...), U> : std::true_type {};
  20. template<typename T, typename U, typename ...Args>
  21. struct is_callable<T(&)(Args...), U> : std::true_type {};
  22. template<typename T, typename U, typename ...Args>
  23. struct is_callable<T(Args......), U> : std::true_type {};
  24. template<typename T, typename U, typename ...Args>
  25. struct is_callable<T(*)(Args......), U> : std::true_type {};
  26. template<typename T, typename U, typename ...Args>
  27. struct is_callable<T(&)(Args......), U> : std::true_type {};
  28. template<typename T, typename U, typename ...Args>
  29. struct is_callable<T(Args...)const, U> : std::true_type {};
  30. template<typename T, typename U, typename ...Args>
  31. struct is_callable<T(Args...)volatile, U> : std::true_type {};
  32. template<typename T, typename U, typename ...Args>
  33. struct is_callable<T(Args...)const volatile, U> : std::true_type {};
  34. template<typename T, typename U, typename ...Args>
  35. struct is_callable<T(Args......)const, U> : std::true_type {};
  36. template<typename T, typename U, typename ...Args>
  37. struct is_callable<T(Args......)volatile, U> : std::true_type{};
  38. template<typename T, typename U, typename ...Args>
  39. struct is_callable<T(Args......)const volatile, U> : std::true_type {};
  40. template<typename T, typename U, typename ...Args>
  41. struct is_callable<T(Args...)&, U> : std::true_type {};
  42. template<typename T, typename U, typename ...Args>
  43. struct is_callable<T(Args...)const&, U> : std::true_type{};
  44. template<typename T, typename U, typename ...Args>
  45. struct is_callable<T(Args...)volatile&, U> : std::true_type{};
  46. template<typename T, typename U, typename ...Args>
  47. struct is_callable<T(Args...)const volatile&, U> : std::true_type{};
  48. template<typename T, typename U, typename ...Args>
  49. struct is_callable<T(Args......)&, U> : std::true_type {};
  50. template<typename T, typename U, typename ...Args>
  51. struct is_callable<T(Args......)const&, U> : std::true_type{};
  52. template<typename T, typename U, typename ...Args>
  53. struct is_callable<T(Args......)volatile&, U> : std::true_type{};
  54. template<typename T, typename U, typename ...Args>
  55. struct is_callable<T(Args......)const volatile&, U> : std::true_type{};
  56. template<typename T, typename U, typename ...Args>
  57. struct is_callable<T(Args...)&&, U> : std::true_type{};
  58. template<typename T, typename U, typename ...Args>
  59. struct is_callable<T(Args...)const&&, U> : std::true_type{};
  60. template<typename T, typename U, typename ...Args>
  61. struct is_callable<T(Args...)volatile&&, U> : std::true_type{};
  62. template<typename T, typename U, typename ...Args>
  63. struct is_callable<T(Args...)const volatile&&, U> : std::true_type{};
  64. template<typename T, typename U, typename ...Args>
  65. struct is_callable<T(Args......)&&, U> : std::true_type{};
  66. template<typename T, typename U, typename ...Args>
  67. struct is_callable<T(Args......)const&&, U> : std::true_type{};
  68. template<typename T, typename U, typename ...Args>
  69. struct is_callable<T(Args......)volatile&&, U> : std::true_type{};
  70. template<typename T, typename U, typename ...Args>
  71. struct is_callable<T(Args......)const volatile&&, U> : std::true_type{};
  72.  
  73. template<typename T>
  74. struct is_callable<T, int>
  75. {
  76. private:
  77. using YesType = char(&)[1];
  78. using NoType = char(&)[2];
  79.  
  80. struct Fallback { void operator()(); };
  81.  
  82. struct Derived : T, Fallback {};
  83.  
  84. template<typename U, U>
  85. struct Check;
  86.  
  87. template<typename>
  88. static YesType Test(...);
  89.  
  90. template<typename C>
  91. static NoType Test(Check<void (Fallback::*)(), &C::operator()>*);
  92.  
  93. public:
  94. static bool const constexpr value = sizeof(Test<Derived>(0)) == sizeof(YesType);
  95. };
  96.  
  97. // END is_callable IMPLEMENTATION
  98.  
  99. struct Callable { void operator()() {} };
  100.  
  101. struct PrivateCallable
  102. {
  103. private:
  104. void operator()(int) {}
  105. double operator()(bool, char*) {}
  106. PrivateCallable(int, int) {}
  107. };
  108.  
  109. struct NotCallable
  110. {
  111. void mFoo() {}
  112. void mConstFoo() const {}
  113. int mInt;
  114. };
  115.  
  116. int foo() {}
  117.  
  118. template<typename ...Args>
  119. void bar(Args &&...args, ...) {}
  120.  
  121. enum WeakTypeEnum {};
  122.  
  123. enum class StrongTypeEnum {};
  124.  
  125. int main(int, char**) noexcept
  126. {
  127. auto pfoo = &foo;
  128. int (&rfoo)() = foo;
  129. auto bfoo = std::bind(&foo);
  130. NotCallable nc;
  131. auto bmfoo = std::bind(&NotCallable::mFoo, &nc);
  132. auto bmcfoo = std::bind(&NotCallable::mConstFoo, &nc);
  133. auto lamb = [](char**) -> decltype(auto)
  134. {
  135. return "Hello World!";
  136. };
  137. std::cout << std::endl << std::boolalpha
  138. << "SCALARS" << std::endl
  139. << "int: " << is_callable<int>::value << std::endl
  140. << "long double: " << is_callable<long double>::value << std::endl
  141. << "int*: " << is_callable<int*>::value << std::endl
  142. << "int const*: " << is_callable<int const*>::value << std::endl
  143. << "int const *const: " << is_callable<int const *const>::value << std::endl
  144. << "WeakTypeEnum: " << is_callable<WeakTypeEnum>::value << std::endl
  145. << "StrongTypeEnum: " << is_callable<StrongTypeEnum>::value << std::endl
  146. << "NotCallable::*: " << is_callable<decltype(&NotCallable::mInt)>::value << std::endl
  147. << "nullptr_t: " << is_callable<decltype(nullptr)>::value << std::endl
  148. << "Callable*: " << is_callable<Callable*>::value << std::endl
  149. << std::endl
  150. << "REFERENCES" << std::endl
  151. << "int&: " << is_callable<int&>::value << std::endl
  152. << "int const&: " << is_callable<int const&>::value << std::endl
  153. << "NotCallable&: " << is_callable<NotCallable&>::value << std::endl
  154. << "NotCallable const&: " << is_callable<NotCallable const&>::value << std::endl
  155. << "Callable&: " << is_callable<Callable&>::value << std::endl
  156. << "Callable const&: " << is_callable<Callable const&>::value << std::endl
  157. << "function reference: " << is_callable<decltype(rfoo)>::value << std::endl
  158. << std::endl
  159. << "FUNCTIONS" << std::endl
  160. << "function (no params): " << is_callable<int()>::value << std::endl
  161. << "function (params): " << is_callable<double(char*)>::value << std::endl
  162. << "function (const): " << is_callable<void(bool) const>::value << std::endl
  163. << "function (ref qualifier): " << is_callable<void(bool)&>::value << std::endl
  164. << "function (rvalue ref qualifier): " << is_callable<void(bool)&&>::value << std::endl
  165. << "function (variadic): " << is_callable<void(...)>::value << std::endl
  166. << "templated variadic function: " << is_callable<decltype(bar<>)>::value << std::endl
  167. << "function pointer: " << is_callable<decltype(pfoo)>::value << std::endl
  168. << "member function pointer: " << is_callable<decltype(&NotCallable::mFoo)>::value << std::endl
  169. << "const member function pointer: " << is_callable<decltype(&NotCallable::mConstFoo)>::value << std::endl
  170. << "bind expression (free function): " << is_callable<decltype(bfoo)>::value << std::endl
  171. << "bind expression (member function): " << is_callable<decltype(bmfoo)>::value << std::endl
  172. << "bind expression (const member function): " << is_callable<decltype(bmcfoo)>::value << std::endl
  173. << "functor: " << is_callable<Callable>::value << std::endl
  174. << "private functor: " << is_callable<PrivateCallable>::value << std::endl
  175. << "std::function: " << is_callable<std::function<int()>>::value << std::endl
  176. << "lambda: " << is_callable<decltype(lamb)>::value << std::endl;
  177. return 0;
  178. }
  179.  
Success #stdin #stdout 0s 3416KB
stdin
Standard input is empty
stdout
SCALARS
int: false
long double: false
int*: false
int const*: false
int const *const: false
WeakTypeEnum: false
StrongTypeEnum: false
NotCallable::*: false
nullptr_t: false
Callable*: false

REFERENCES
int&: false
int const&: false
NotCallable&: false
NotCallable const&: false
Callable&: true
Callable const&: true
function reference: true

FUNCTIONS
function (no params): true
function (params): true
function (const): true
function (ref qualifier): true
function (rvalue ref qualifier): true
function (variadic): true
templated variadic function: true
function pointer: true
member function pointer: false
const member function pointer: false
bind expression (free function): true
bind expression (member function): true
bind expression (const member function): true
functor: true
private functor: true
std::function: true
lambda: true