fork(3) download
  1. #include <iostream>
  2. #include <type_traits>
  3.  
  4. template<typename CLASS>
  5. struct has_begin
  6. {
  7. // NOTE: sig_matches() must come before fn_exists() as it is used for its
  8. // type. No function bodies are needed as they are never called.
  9.  
  10. // This matching sig results in a return type of true_type
  11. template<typename A_CLASS>
  12. static auto
  13. sig_matches(void(A_CLASS::*)())
  14. -> std::true_type;
  15.  
  16. // If the member function A_CLASS::begin exists and a sig_matches() function
  17. // exists with the required sig, then the return type is the return type of
  18. // sig_matches(), otherwise this function can't exist because at least one
  19. // the types don't exist so match against fn_exists(...).
  20. template <typename A_CLASS>
  21. static auto
  22. fn_exists(std::nullptr_t)
  23. -> decltype(sig_matches<A_CLASS>(&A_CLASS::begin));
  24.  
  25. // Member function either doesn't exist or doesn't match against a
  26. // sig_matches() function.
  27. template<typename A_CLASS>
  28. static auto
  29. fn_exists(...)
  30. -> std::false_type;
  31.  
  32. // Intermediate storeage of type for clarity
  33. typedef decltype(fn_exists<CLASS>(nullptr)) type;
  34.  
  35. // Storing the resulting value
  36. static int const value = type::value;
  37. };
  38.  
  39.  
  40. struct A
  41. {
  42. void begin()
  43. {
  44. std::cout << "begin() called 1" << std::endl;
  45. }
  46. };
  47.  
  48. struct B
  49. {
  50. };
  51.  
  52. struct C
  53. {
  54. void begin()
  55. {
  56. std::cout << "begin() called 1" << std::endl;
  57. }
  58.  
  59. void begin(float)
  60. {
  61. std::cout << "begin() called 2" << std::endl;
  62. }
  63. };
  64.  
  65. template<typename T, typename...ARGs>
  66. typename std::enable_if<!!has_begin<T>::value>::type
  67. call(ARGs...args)
  68. {
  69. std::cout << "Found(" << has_begin<T>::value << ")" << std::endl;
  70. T().begin(args...);
  71. }
  72.  
  73. template<typename T, typename...ARGs>
  74. typename std::enable_if<!has_begin<T>::value>::type
  75. call(ARGs...)
  76. {
  77. std::cout << "NOT Found(" << has_begin<T>::value << ")" << std::endl;
  78. }
  79.  
  80. int main()
  81. {
  82. call<A>(); // A::begin() called
  83. call<B>(); // B has no begin()
  84. call<C>(); // C::begin() is not called.
  85. return 0;
  86. }
  87.  
Success #stdin #stdout 0s 3096KB
stdin
Standard input is empty
stdout
Found(1)
begin() called 1
NOT Found(0)
Found(1)
begin() called 1