fork(2) download
  1. #include <type_traits>
  2. #include <utility>
  3.  
  4. namespace util
  5. {
  6. template <typename T>
  7. struct always_void
  8. {
  9. typedef void type;
  10. };
  11. }
  12.  
  13. namespace detail
  14. {
  15. template <typename T, typename Args, typename Enable = void>
  16. struct is_callable_impl
  17. : std::false_type
  18. {};
  19.  
  20. template <typename T, typename... A>
  21. struct is_callable_impl<T, void(A...)
  22. , typename util::always_void<
  23. decltype(std::declval<T>()(std::declval<A>()...))
  24. >::type
  25. > : std::true_type
  26. {};
  27.  
  28. template <typename T, typename C>
  29. struct is_callable_impl<T, void(C)
  30. , typename util::always_void<
  31. decltype(
  32. (std::declval<typename std::remove_pointer<C>::type>()
  33. .*std::declval<T>()))
  34. >::type
  35. > : std::true_type
  36. {};
  37.  
  38. template <typename T, typename C, typename... A>
  39. struct is_callable_impl<T, void(C, A...)
  40. , typename util::always_void<
  41. decltype(
  42. (std::declval<typename std::remove_pointer<C>::type>()
  43. .*std::declval<T>())(std::declval<A>()...))
  44. >::type
  45. > : std::true_type
  46. {};
  47. }
  48.  
  49. template <typename T, typename... A>
  50. struct is_callable
  51. : detail::is_callable_impl<T, void(A...)>
  52. {};
  53.  
  54. struct X {};
  55.  
  56. int main()
  57. {
  58. static_assert(is_callable<void (X::*)(int) const, X&, int>::value, "increment::call");
  59.  
  60. auto lambda = [](){};
  61. static_assert(is_callable<decltype(lambda)>::value, "");
  62. static_assert(is_callable<void()>::value, "");
  63.  
  64. static_assert(is_callable<int (X::*)(double), X*, float>::value, "");
  65. static_assert(!is_callable<int (X::*)(double), X const*, float>::value, "");
  66. static_assert(is_callable<int (X::*)(double), X&, float>::value, "");
  67. static_assert(!is_callable<int (X::*)(double), X const&, float>::value, "");
  68. static_assert(is_callable<int (X::*)(double) const, X*, float>::value, "");
  69. static_assert(is_callable<int (X::*)(double) const, X const*, float>::value, "");
  70. static_assert(is_callable<int (X::*)(double) const, X&, float>::value, "");
  71. static_assert(is_callable<int (X::*)(double) const, X const&, float>::value, "");
  72.  
  73. static_assert(is_callable<int (X::*), X*>::value, "");
  74. static_assert(is_callable<int (X::*), X const*>::value, "");
  75. static_assert(is_callable<int (X::*), X&>::value, "");
  76. static_assert(is_callable<int (X::*), X const&>::value, "");
  77. static_assert(is_callable<int (X::*), X&&>::value, "");
  78. static_assert(is_callable<int (X::*), X const&&>::value, "");
  79.  
  80. static_assert(!is_callable<void(int&), int>::value, "");
  81. static_assert(is_callable<void(int&), int&>::value, "");
  82. static_assert(!is_callable<void(int&), int const&>::value, "");
  83. static_assert(!is_callable<void(int&), int&&>::value, "");
  84. static_assert(!is_callable<void(int&), int const&&>::value, "");
  85.  
  86. static_assert(is_callable<void(int const&), int>::value, "");
  87. static_assert(is_callable<void(int const&), int&>::value, "");
  88. static_assert(is_callable<void(int const&), int const&>::value, "");
  89. static_assert(is_callable<void(int const&), int&&>::value, "");
  90. static_assert(is_callable<void(int const&), int const&&>::value, "");
  91.  
  92. static_assert(is_callable<void(int&&), int>::value, "");
  93. static_assert(!is_callable<void(int&&), int&>::value, "");
  94. static_assert(!is_callable<void(int&&), int const&>::value, "");
  95. static_assert(is_callable<void(int&&), int&&>::value, "");
  96. static_assert(!is_callable<void(int&&), int const&&>::value, "");
  97.  
  98. static_assert(is_callable<void(int const&&), int>::value, "");
  99. static_assert(!is_callable<void(int const&&), int&>::value, "");
  100. static_assert(!is_callable<void(int const&&), int const&>::value, "");
  101. static_assert(is_callable<void(int const&&), int&&>::value, "");
  102. static_assert(is_callable<void(int const&&), int const&&>::value, "");
  103.  
  104. return 0;
  105. }
  106.  
Success #stdin #stdout 0s 3292KB
stdin
Standard input is empty
stdout
Standard output is empty