fork download
  1. #include <tuple>
  2. #include <type_traits>
  3. #include <functional>
  4.  
  5. // functor
  6.  
  7. template<class Func, class... Args>
  8. class is_callable
  9. {
  10. using yes = char(&)[2];
  11. using no = char(&)[1];
  12.  
  13. template<class F>
  14. static yes check(decltype(std::declval<F&>()(std::declval<Args>()...))*);
  15.  
  16. template<class F>
  17. static no check(...);
  18. public:
  19. enum { value = (sizeof(check<Func>(nullptr)) == sizeof(yes)) };
  20. };
  21.  
  22. // member function
  23.  
  24. template<typename Class, typename MemFunc, class... Args>
  25. class is_callable_member_function
  26. {
  27. using yes = char(&)[2];
  28. using no = char(&)[1];
  29.  
  30. template<class C, class MF>
  31. static yes check(decltype((std::declval<C>().*std::declval<MF>())(std::declval<Args>()...))*);
  32.  
  33. template<class C, class MF>
  34. static no check(...);
  35. public:
  36. enum { value = (sizeof(check<Class, MemFunc>(nullptr)) == sizeof(yes)) };
  37. };
  38.  
  39. //////////////////////////////////
  40.  
  41. template<typename Func, typename... Args>
  42. void assert_is_callable(Func&&, Args&&...)
  43. {
  44. static_assert(is_callable<Func, Args...>::value,
  45. "the provided type is not callable with the supplied arguments");
  46. }
  47.  
  48. template<typename Class, typename MemFunc, typename... Args>
  49. void assert_is_callable(Class*, MemFunc, Args&&...)
  50. {
  51. static_assert(is_callable_member_function<Class, MemFunc, Args...>::value,
  52. "the provided type is not callable with the supplied arguments");
  53. }
  54.  
  55. //////////////////////////////////
  56.  
  57. struct Foo
  58. {
  59. void func(int, double, char)
  60. {
  61. }
  62. };
  63.  
  64. void func(int, double, char)
  65. {
  66. }
  67.  
  68. int main()
  69. {
  70. // member function
  71. Foo f;
  72. assert_is_callable(&f, &Foo::func, 1, 2.3, 'c');
  73.  
  74. // lambda
  75. auto lambda = [](int, double, char) { };
  76. assert_is_callable(lambda, 1, 2.3, 'c');
  77.  
  78. // free function
  79. assert_is_callable(func, 1, 2.3, 'c'); // selects the member_function version
  80.  
  81. return 0;
  82. }
  83.  
Compilation error #stdin compilation error #stdout 0s 3456KB
stdin
Standard input is empty
compilation info
prog.cpp: In instantiation of 'void assert_is_callable(Class*, MemFunc, Args&& ...) [with Class = void(int, double, char); MemFunc = int; Args = {double, char}]':
prog.cpp:79:41:   required from here
prog.cpp:51:5: error: static assertion failed: the provided type is not callable with the supplied arguments
     static_assert(is_callable_member_function<Class, MemFunc, Args...>::value,
     ^
stdout
Standard output is empty