Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <type_traits>
- #include <iostream>
- namespace thirdparty {
- template<class Derived>
- struct Greeter
- {
- #define HAS_MEMBER(name) \
- template <class C> \
- struct has_##name { \
- private: \
- template <class T> \
- constexpr static std::true_type check(decltype(&T::name)); \
- template<class T> \
- constexpr static std::false_type check(...); \
- public: \
- constexpr static bool value = decltype(check<C>(nullptr))::value; \
- }; \
- template<class C> inline static constexpr bool has_##name##_v = has_##name<C>::value; \
- template<class C> inline static constexpr bool has_##name##_v_n = !has_##name##_v<C>;
- #define DEFINE_METHOD(name) \
- HAS_MEMBER(name) \
- \
- template<class T = Derived, std::enable_if_t<has_##name##_v<T>, int> = 0> \
- void name() { reinterpret_cast<Derived *>(this)->name(); } \
- \
- template<class T = Derived, std::enable_if_t<has_##name##_v_n<T>, int> = 0> \
- void name() { std::cout << "base\n"; }
- DEFINE_METHOD(greet)
- DEFINE_METHOD(print_name)
- };
- template<class Derived>
- void call_greet(Greeter<Derived> * greeter)
- { greeter->greet(); }
- template<class Derived>
- void call_name(Greeter<Derived> * greeter)
- { greeter->print_name(); }
- } // namespace thirdparty
- struct MyGreeter : public thirdparty::Greeter<MyGreeter>
- {
- void greet()
- {
- std::cout << "hi\n";
- }
- };
- struct SilentGreeter : public thirdparty::Greeter<SilentGreeter>
- {
- void print_name()
- {
- std::cout << "silent greeter\n";
- }
- };
- int main() {
- MyGreeter g1;
- SilentGreeter g2;
- thirdparty::call_greet(&g1); // > hi
- thirdparty::call_greet(&g2); // > base
- std::cout << '\n';
- thirdparty::call_name(&g1); // > base
- thirdparty::call_name(&g2); // > silent greeter
- }
Add Comment
Please, Sign In to add comment