Skip to content

Instantly share code, notes, and snippets.

@artivis
Last active March 20, 2018 13:47
Show Gist options
  • Save artivis/e53c3d67ef5100da909dc99b4a842995 to your computer and use it in GitHub Desktop.
Save artivis/e53c3d67ef5100da909dc99b4a842995 to your computer and use it in GitHub Desktop.
Fun with CRTP
// Example program
#include <iostream>
#include <string>
template<class, typename T, class...> struct has_speak_m_impl : std::false_type {};
template<typename T, class... Args> struct has_speak_m_impl<decltype( std::declval<T>().speak(std::declval<Args...>()) ), T> : std::true_type {};
template<typename T, class... Args> struct has_speak_m : has_speak_m_impl<void, T, Args...> {};
template <typename Derived>
struct BaseInterface
{
template <typename... Ts>
typename std::enable_if<has_speak_m<Derived, Ts...>::value>::type
speak(Ts&&... val)
{
//calling Derived speak
derived().speak(std::forward<Ts>(val)...);
}
template <typename... Ts>
typename std::enable_if<!has_speak_m<Derived, Ts...>::value>::type
speak(Ts&&...)
{
std::cout << "default speak.\n";
}
protected:
constexpr Derived& derived() { return static_cast< Derived& >(*this); }
};
struct DerivedA : BaseInterface<DerivedA>
{
void speak(const int val) const { std::cout << "DerivedA speak : " << val << "\n"; }
};
struct DerivedB : BaseInterface<DerivedB>
{
template <typename T> int speak(const T& val) const { std::cout << "DerivedB speak : " << val << "\n"; return 0; }
};
struct DerivedC : BaseInterface<DerivedC> { };
struct DerivedD : BaseInterface<DerivedD> { int speak_impl; };
struct DerivedE : BaseInterface<DerivedE> { using speak_impl = int; };
int main()
{
DerivedA derived_a;
DerivedB derived_b;
DerivedC derived_c;
DerivedD derived_d;
DerivedE derived_e;
derived_a.speak(0);
derived_b.speak("1");
derived_c.speak(3,3);
derived_d.speak(3,3);
derived_e.speak();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment