#include <iostream>
#include <type_traits>
#include <typeinfo>
template <class T> struct type_printer { static void print() { std::cout << typeid(T).name(); } };
template <class T> struct type_printer<T const> { static void print() { type_printer<T>::print(); std::cout << " const"; } };
template <class T> struct type_printer<T*> { static void print() { type_printer<T>::print(); std::cout << " *"; } };
template <class T> struct type_printer<T&> { static void print() { type_printer<T>::print(); std::cout << " &"; } };
#define printtype(...) type_printer<__VA_ARGS__>::print()
#define printtype_line(...) do { std::cout << #__VA_ARGS__ ": " << std::endl; printtype(__VA_ARGS__); std::cout << std::endl; } while (0)
template<typename Derived>
struct base
{
void const_method() const
{
static_cast<Derived*>(this)->method();
}
void fixed_const_method() const
{
// base<derived> const*
printtype_line(decltype(this));
// base<derived>
printtype_line(typename std::remove_pointer<decltype(this)>::type);
// base<derived>
printtype_line(decltype(*this));
// derived const*
printtype_line(typename std::conditional<
std::is_const<
typename std::remove_pointer<decltype(this)>::type>::value,
Derived const* const,
Derived* const>::type);
static_cast<
typename std::conditional<
std::is_const<
typename std::remove_pointer<decltype(this)>::type>::value,
Derived const* const,
Derived* const>::type>(this)->method();
}
};
struct derived : public base<derived>
{
void method() const
{
std::cout << "const method" << std::endl;
}
void method()
{
std::cout << "non-const method" << std::endl;
}
};
int main()
{
derived d;
d.fixed_const_method();
return 0;
}