EeZotop

Derived has method check

Aug 27th, 2020 (edited)
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 1.77 KB | None | 0 0
  1. #include <type_traits>
  2. #include <iostream>
  3.  
  4. namespace thirdparty {
  5.  
  6. template<class Derived>
  7. struct Greeter
  8. {
  9. #define HAS_MEMBER(name) \
  10. template <class C> \
  11. struct has_##name { \
  12. private: \
  13.     template <class T> \
  14.     constexpr static std::true_type check(decltype(&T::name)); \
  15.     template<class T> \
  16.     constexpr static std::false_type check(...); \
  17. public: \
  18.     constexpr static bool value = decltype(check<C>(nullptr))::value; \
  19. }; \
  20. template<class C> inline static constexpr bool has_##name##_v = has_##name<C>::value; \
  21. template<class C> inline static constexpr bool has_##name##_v_n = !has_##name##_v<C>;
  22.  
  23. #define DEFINE_METHOD(name) \
  24. HAS_MEMBER(name) \
  25. \
  26.     template<class T = Derived, std::enable_if_t<has_##name##_v<T>, int> = 0> \
  27.     void name() { reinterpret_cast<Derived *>(this)->name(); } \
  28. \
  29.     template<class T = Derived, std::enable_if_t<has_##name##_v_n<T>, int> = 0> \
  30.     void name() { std::cout << "base\n"; }
  31.  
  32.     DEFINE_METHOD(greet)
  33.     DEFINE_METHOD(print_name)
  34.  
  35. };
  36.  
  37. template<class Derived>
  38. void call_greet(Greeter<Derived> * greeter)
  39. { greeter->greet(); }
  40.  
  41. template<class Derived>
  42. void call_name(Greeter<Derived> * greeter)
  43. { greeter->print_name(); }
  44.  
  45. } // namespace thirdparty
  46.  
  47.  
  48. struct MyGreeter : public thirdparty::Greeter<MyGreeter>
  49. {
  50.     void greet()
  51.     {
  52.         std::cout << "hi\n";
  53.     }
  54. };
  55.  
  56. struct SilentGreeter : public thirdparty::Greeter<SilentGreeter>
  57. {
  58.     void print_name()
  59.     {
  60.         std::cout << "silent greeter\n";
  61.     }
  62. };
  63.  
  64. int main() {
  65.     MyGreeter g1;
  66.     SilentGreeter g2;
  67.  
  68.     thirdparty::call_greet(&g1); // > hi
  69.     thirdparty::call_greet(&g2); // > base
  70.  
  71.     std::cout << '\n';
  72.  
  73.     thirdparty::call_name(&g1); // > base
  74.     thirdparty::call_name(&g2); // > silent greeter
  75. }
  76.  
Add Comment
Please, Sign In to add comment