
#include <iostream>
using namespace std;

    #define DECLARE_SELF(Type) \
        typedef Type TySelf; /**< @brief type of this class */ \
        /** checks the consistency of TySelf type (calling it has no effect) */ \
        void self_check() \
        { \
            static_assert(std::is_same<decltype(*((TySelf*)(0))), \
                decltype(*this)>::value, "TySelf is not what it should be"); \
        } \
        enum { static_self_check_token = __LINE__ }; \
        static_assert(int(static_self_check_token) == \
            int(TySelf::static_self_check_token), \
            "TySelf is not what it should be")

    struct ABC {
        DECLARE_SELF(ABC);
    };
    
    struct XYZ {
        DECLARE_SELF(ABC); // fails
    	//DECLARE_SELF(XYZ); // runs
    };
    
    template <class MyArg>
    struct XYZt {
        DECLARE_SELF(ABC); // fails, if XYZt is instantiated
        //DECLARE_SELF(XYZt); // runs
    };
    

int main() {
	XYZt<int> instantiate_me;
	
	return 0;
}