#include <iostream>
#include <string>
//==============================
// convert template type to string
template<typename>
struct template_to_string {
    static std::string value() { return "unknown"; }
};

#define DEFINE_TYPE(X) \
    struct X; \
    template<> struct template_to_string<X> { \
        static std::string value() { return #X; } \
    };

//==============================
template<class T>
struct ShowClass
{
    ShowClass() {
        std::cout << template_to_string<T>::value()
                  << " show" << std::endl;
                }
};

//==============================
template <typename T>
struct AutoShow
{
    AutoShow() { std::cout << "AutoShow ctor" << std::endl; &our_show; }
    
protected:
    static ShowClass<T> our_show;
};
template <typename T>
ShowClass<T> AutoShow<T>::our_show;


//==============================
DEFINE_TYPE(Test)
struct Test
{
private:
    static ShowClass<Test> our_show;
};
ShowClass<Test> Test::our_show;

//==============================
DEFINE_TYPE(TestOK)
struct TestOK : public AutoShow<TestOK>
{
    TestOK() {}
};

//==============================
DEFINE_TYPE(TestFail)
struct TestFail : public AutoShow<TestFail>
{
};

//==============================
int main()
{
    return 0;
}
