fork download
  1. #include <iostream>
  2. #include <utility>
  3. #include <type_traits>
  4.  
  5.  
  6. namespace detail {
  7.  
  8. template<typename T>
  9. class has_noarg_foo_method {
  10.  
  11. using yes = char(&)[1];
  12. using no = char(&)[2];
  13.  
  14. template<typename>
  15. struct helper;
  16.  
  17. template<typename>
  18. static no check(...);
  19.  
  20. template<typename U>
  21. static yes check(helper<decltype(std::declval<U>().foo())> *);
  22.  
  23. public:
  24. static constexpr bool value = sizeof (check<T>(nullptr)) == sizeof (yes);
  25. };
  26.  
  27. }
  28.  
  29. template<typename T>
  30. struct has_noarg_foo_method : std::integral_constant<bool, detail::has_noarg_foo_method<T>::value> {};
  31.  
  32.  
  33. struct one {
  34.  
  35. void foo() const {
  36. std::cout << "foo()" << std::endl;
  37. }
  38. };
  39.  
  40. struct two {
  41.  
  42. void foo(int x) const {
  43. std::cout << "foo(" << x << ")" << std::endl;
  44. }
  45. };
  46.  
  47. namespace detail {
  48.  
  49. enum class enabler;
  50.  
  51. }
  52.  
  53. template<typename T>
  54. using enable_if = typename std::enable_if<T::value, detail::enabler>::type;
  55.  
  56. template<typename T>
  57. using disable_if = typename std::enable_if<!T::value, detail::enabler>::type;
  58.  
  59. template<typename T, enable_if<has_noarg_foo_method<T>>...>
  60. void do_foo(T const& obj, int) {
  61. obj.foo();
  62. }
  63.  
  64. template<typename T, disable_if<has_noarg_foo_method<T>>...>
  65. void do_foo(T const& obj, int const x) {
  66. obj.foo(x);
  67. }
  68.  
  69.  
  70. int main() {
  71. do_foo(one{}, 1);
  72. do_foo(two{}, 2);
  73. }
Success #stdin #stdout 0s 3296KB
stdin
Standard input is empty
stdout
foo()
foo(2)