fork(4) download
  1. #ifndef MPL_IS_CALLABLE_HPP
  2. #define MPL_IS_CALLABLE_HPP
  3.  
  4. #include <type_traits>
  5.  
  6. namespace mpl
  7. {
  8. namespace // implementation detail
  9. {
  10. // build R (*)(Args...) from R (Args...)
  11. // compile error if signature is not a valid function signature
  12. template <typename, typename>
  13. struct build_free_function;
  14.  
  15. template <typename F, typename R, typename ... Args>
  16. struct build_free_function<F, R (Args...)>
  17. { using type = R (*)(Args...); };
  18.  
  19. // build R (C::*)(Args...) from R (Args...)
  20. // R (C::*)(Args...) const from R (Args...) const
  21. // R (C::*)(Args...) volatile from R (Args...) volatile
  22. // compile error if signature is not a valid member function signature
  23. template <typename, typename>
  24. struct build_class_function;
  25.  
  26. template <typename C, typename R, typename ... Args>
  27. struct build_class_function<C, R (Args...)>
  28. { using type = R (C::*)(Args...); };
  29.  
  30. template <typename C, typename R, typename ... Args>
  31. struct build_class_function<C, R (Args...) const>
  32. { using type = R (C::*)(Args...) const; };
  33.  
  34. template <typename C, typename R, typename ... Args>
  35. struct build_class_function<C, R (Args...) volatile>
  36. { using type = R (C::*)(Args...) volatile; };
  37.  
  38. // determine whether a class C has an operator() with signature S
  39. template <typename C, typename S>
  40. struct is_functor_with_signature
  41. {
  42. typedef char (& yes)[1];
  43. typedef char (& no)[2];
  44.  
  45. // helper struct to determine that C::operator() does indeed have
  46. // the desired signature; &C::operator() is only of type
  47. // R (C::*)(Args...) if this is true
  48. template <typename T, T> struct check;
  49.  
  50. // T is needed to enable SFINAE
  51. template <typename T> static yes deduce(check<
  52. typename build_class_function<C, S>::type, &T::operator()> *);
  53. // fallback if check helper could not be built
  54. template <typename> static no deduce(...);
  55.  
  56. static bool constexpr value = sizeof(deduce<C>(0)) == sizeof(yes);
  57. };
  58.  
  59. // determine whether a free function pointer F has signature S
  60. template <typename F, typename S>
  61. struct is_function_with_signature
  62. {
  63. // check whether F and the function pointer of S are of the same
  64. // type
  65. static bool constexpr value = std::is_same<
  66. F, typename build_free_function<F, S>::type
  67. >::value;
  68. };
  69.  
  70. // C is a class, delegate to is_functor_with_signature
  71. template <typename C, typename S, bool>
  72. struct is_callable_impl
  73. : std::integral_constant<
  74. bool, is_functor_with_signature<C, S>::value
  75. >
  76. {};
  77.  
  78. // F is not a class, delegate to is_function_with_signature
  79. template <typename F, typename S>
  80. struct is_callable_impl<F, S, false>
  81. : std::integral_constant<
  82. bool, is_function_with_signature<F, S>::value
  83. >
  84. {};
  85. }
  86.  
  87. // Determine whether type Callable is callable with signature Signature.
  88. // Compliant with functors, i.e. classes that declare operator(); and free
  89. // function pointers: R (*)(Args...), but not R (Args...)!
  90. template <typename Callable, typename Signature>
  91. struct is_callable
  92. : is_callable_impl<
  93. Callable, Signature,
  94. std::is_class<Callable>::value
  95. >
  96. {};
  97.  
  98. namespace // tests
  99. {
  100. struct A { void operator()(); };
  101. struct B {};
  102. struct C {
  103. int operator()(int &, void **) const;
  104. int operator()(double);
  105. };
  106. void a();
  107. int b;
  108. int c(int &, void **);
  109. int c(double);
  110.  
  111. #define MPL_IS_CALLABLE_POSITIVE "should be recognized as callable"
  112. #define MPL_IS_CALLABLE_NEGATIVE "should not be recognized as callable"
  113. static_assert(is_callable<A, void ()>::value, MPL_IS_CALLABLE_POSITIVE);
  114. static_assert(!is_callable<B, void ()>::value, MPL_IS_CALLABLE_NEGATIVE);
  115. static_assert(is_callable<C, int (int &, void **) const>::value, MPL_IS_CALLABLE_POSITIVE);
  116. static_assert(is_callable<C, int (double)>::value, MPL_IS_CALLABLE_POSITIVE);
  117. static_assert(is_callable<decltype(&a), void ()>::value, MPL_IS_CALLABLE_POSITIVE);
  118. static_assert(!is_callable<decltype(&b), void ()>::value, MPL_IS_CALLABLE_NEGATIVE);
  119. static_assert(is_callable<decltype(static_cast<int (*)(int &, void **)>(&c)), int (int &, void **)>::value, MPL_IS_CALLABLE_POSITIVE);
  120. static_assert(is_callable<decltype(static_cast<int (*)(double)>(&c)), int (double)>::value, MPL_IS_CALLABLE_POSITIVE);
  121. #undef MPL_IS_CALLABLE_POSITIVE
  122. #undef MPL_IS_CALLABLE_NEGATIVE
  123. }
  124. }
  125.  
  126. #endif // MPL_IS_CALLABLE_HPP
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
/usr/lib/gcc/i486-linux-gnu/4.8/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: error: ld returned 1 exit status
stdout
Standard output is empty