    // BEGIN TYPE_CHECK.H
    // https://w...content-available-to-author-only...x.com/s/dkft2pcur5y76aq/type_check.h
    #ifndef TYPE_CHECK_H
    #define TYPE_CHECK_H
     
     
    //------------------------------------------------------------------------------
    // TYPE_CHECK()
     
    /** Type Check.
     * Test type `T_` for the presence or absence of type `T_::TYPE_`.
     * This Provides a convenient frontend for a SFINAE (substitution failure is
     * not an error) idiom.
     *
     * Defines a `struct NAME_` which is instantiated with `HAS_TYPE_` as its body
     * for types `T_` when `T_::TYPE_` exists, and with `NO_TYPE_` as its body for
     * types `T_` which don't have a `T_::TYPE_`. `HAS_TYPE_` and `NO_TYPE_` can
     * contain multiple declarations, which should be seperated by `;` (as in a
     * normal `struct` body).
     *
     * A trailing `;` is provided for the last declaration by the macro, so this can
     * be omitted at the point of use. Unless the flag TYPE_CHECK_NO_VA_ARGS is
     * #defined, then `HAS_TYPE_` and `NO_TYPE_` can be parenthesized if necessary
     * (if they contain unparenthesized commas, for example).
     * \sa TYPE_CHECK_FRIEND()
     */
    #define TYPE_CHECK(NAME_, T_, TYPE_, HAS_TYPE_, NO_TYPE_) \
      template<typename T_, typename = void>struct NAME_ { \
      tc_STRIP_PARENS(NO_TYPE_); \
      }; \
      template<typename T_> \
      struct NAME_<T_, \
      typename ::tc_::HasType<typename T_::TYPE_>::Type> { \
      tc_STRIP_PARENS(HAS_TYPE_); \
      }
     
     
    //------------------------------------------------------------------------------
    // TYPE_CHECK_FRIEND()
     
    /** Type Check Friend.
     * This macro can be placed in a type declaration, to indicate that the body of
     * the check defined as `NAME_` can acces this type's protected/private members.
     * \sa TYPE_CHECK()
     */
    #define TYPE_CHECK_FRIEND(NAME_) \
      template<typename, typename>friend struct NAME_;
     
     
    //------------------------------------------------------------------------------
    // Internal details follow...
     
    #ifndef TYPE_CHECK_NO_VA_ARGS
     
    // Detect and strip parentheses from __VA_ARGS__.
    #define tc_STRIP_PARENS(...) \
      tc_IF( tc_HAS_PARENS(__VA_ARGS__), \
      tc_PASSTHROUGH(tc_PASSTHROUGH __VA_ARGS__), \
      tc_PASSTHROUGH(__VA_ARGS__) )
     
    #define tc_IF(COND_, TRUE_, FALSE_) \
      tc_JOIN2(tc_DO_IF_, tc_NEQ(COND_, 0)) \
      (tc_PASSTHROUGH(TRUE_), tc_PASSTHROUGH(FALSE_))
    #define tc_DO_IF_0(T_, F_) F_
    #define tc_DO_IF_1(T_, F_) T_
     
    #define tc_HAS_PARENS(...) \
      tc_NEQ( tc_COMMA_COUNT(__VA_ARGS__), \
      tc_COMMA_COUNT(tc_COMMA_IF_PARENS __VA_ARGS__) )
     
    #define tc_NEQ(A_, B_) tc_DO_NEQ(A_, B_)
    #define tc_DO_NEQ(A_, B_) tc_DO_NEQ_##A_##B_
    #define tc_DO_NEQ_00 0
    #define tc_DO_NEQ_01 1
    #define tc_DO_NEQ_10 1
    #define tc_DO_NEQ_11 0
     
    #define tc_JOIN2(A_, B_) tc_DO_JOIN2(A_, B_)
    #define tc_DO_JOIN2(A_, B_) A_##B_
     
    #define tc_PASSTHROUGH(...) __VA_ARGS__
    #define tc_COMMA_IF_PARENS(...) ,
     
    // counts commas in (...)
    #define tc_COMMA_COUNT(...) tc_LAST_ARG(__VA_ARGS__, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
    #define tc_LAST_ARG(a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_, m_, n_, o_, p_, q_, r_, s_, t_, u_, v_, w_, x_, y_, z_, ...) z_
     
    #else//TYPE_CHECK_NO_VA_ARGS
     
    // Default case for compilers with no __VA_ARGS__ support
    #define tc_STRIP_PARENS(X_) X_
     
    #endif//TYPE_CHECK_NO_VA_ARGS
     
    //------------------------------------------------------------------------------
    //
    namespace tc_ {
    template<typename T> struct HasType { typedef void Type; };
    } // namespace type_check_
     
     
    #endif//TYPE_CHECK_H
    // END TYPE_CHECK.H
     
    // BEGIN MAIN.CPP
    // https://w...content-available-to-author-only...x.com/s/5mg4190ao3o9tgd/main.cpp
    //#include "type_check.h" // it's right above this!
     
    #include <stdio.h>
    #include <stdlib.h>
     
     
    const char *strbool(bool b) { return b ? "true" : "false"; }
     
    // testing structs
    struct TestingF {}; // No TestingF::TypeToCheck exists
    struct TestingT { typedef void TypeToCheck; };
     
     
    //------------------------------------------------------------------------------
    // Test 1
    // Simple true/false check.
     
    TYPE_CHECK(Test1Check, T, TypeToCheck,
    static const bool VALUE = true, // Test1Check body when T::TypeToCheck exists
    static const bool VALUE = false); //Test1Check body default
     
    bool test1() {
     
    bool f = Test1Check<TestingF>::VALUE; // -> false
    bool t = Test1Check<TestingT>::VALUE; // -> true
     
    printf("t = %s, f = %s\n", strbool(t), strbool(f));
     
    return !f && t;
    }
     
     
    #ifndef TYPE_CHECK_NO_VA_ARGS
    //------------------------------------------------------------------------------
    // Test 2
    // Parens around the 'body' clauses to handle the commas in the int declarations.
     
    TYPE_CHECK( Test2Check, T, TypeToCheck,
    (static const int a = 10, b = 20, c = 30),
    (static const int a = 3, b = 4, c = 5) );
     
    bool test2() {
     
    typedef Test2Check<TestingF> T2F;
    typedef Test2Check<TestingT> T2T;
     
    int sum_f = T2F::a + T2F::b + T2F::c;
    int sum_t = T2T::a + T2T::b + T2T::c;
     
    printf("sum_f = %u, sum_t = %u\n", sum_f, sum_t);
     
    return (12 == sum_f) && (60 == sum_t);
    }
    #endif//TYPE_CHECK_NO_VA_ARGS
     
     
    //------------------------------------------------------------------------------
    // Test 3
    // Select functions.
     
    TYPE_CHECK( Test3Check, T, TypeToCheck,
    static int test(int &a) { return ++a; }, // trailing comma needed here!
    static int test(int &a) { return --a; } );
     
    bool test3() {
     
    int q =10;
    typedef Test3Check<TestingF> T3F;
    typedef Test3Check<TestingT> T3T;
     
    int u = T3F::test(q);
    int v = T3F::test(q);
    int w = T3F::test(q);
    int x = T3T::test(q);
    int y = T3T::test(q);
    int z = T3T::test(q);
     
    printf("%u, %u, %u, %u, %u, %u\n", u, v, w, x, y, z);
     
    return
    (9 == u) && (8 == v) && (7 == w) &&
    (8 == x) && (9 == y) && (10 == z) &&
    true;
    }
     
     
    //------------------------------------------------------------------------------
    // Test 4
    // private implementations and TYPE_CHECK_FRIEND()
     
    class Test4ExampleF {};
    class Test4ExampleT {
    typedef int TypeToCheck;
    TYPE_CHECK_FRIEND(Test4Check); // Give Test4Check access to internals
    };
     
    TYPE_CHECK(Test4Check, T, TypeToCheck,
    static const bool VALUE = true, // Test4Check body when T::TypeToCheck exists
    static const bool VALUE = false); //Test4Check body default
     
    bool test4() {
     
    bool f = Test4Check<Test4ExampleF>::VALUE; // -> false
    bool t = Test4Check<Test4ExampleT>::VALUE; // -> true
     
    printf("t = %s, f = %s\n", strbool(t), strbool(f));
     
    return !f && t;
    }
     
     
    //------------------------------------------------------------------------------
    // Test 5
    // Something a bit more like 'real-world' usage.
     
    // Use the HAS_SPECIAL_METHOD() macro in a type declaration to arrange for
    // Test5Check<X>::result() to call the named method...
    #define HAS_SPECIAL_METHOD(NAME_) \
      typedef void HasSpecialMethod; /* the tag */\
      int do_special_() { return NAME_(); } /* indirect call to NAME_() */
     
    struct Test5Default {
    Test5Default(int d): data(d) {}
    int data;
    };
     
    struct Test5Special1 {
    Test5Special1(int d): data(d) {}
    int data;
     
    int special1() { return data * 4; }
    HAS_SPECIAL_METHOD(special1);
    };
     
    struct Test5Special2 {
    Test5Special2(int d): data(d) {}
    int data;
     
    int special2() { return data - 100; }
    HAS_SPECIAL_METHOD(special2);
    };
     
    // use X instead of T for fun...
    TYPE_CHECK(Test5Check, X, HasSpecialMethod,
     
    static int result(X &x) {
    return x.do_special_();
    },
     
    static int result(X &x) { return x.data; } );
     
    template<typename X>
    int test5result(X &x) { return Test5Check<X>::result(x); }
     
    bool test5() {
    Test5Default def(100);
    Test5Special1 sp1(100);
    Test5Special2 sp2(100);
     
    printf("%d, %d, %d\n",
    test5result(def),
    test5result(sp1),
    test5result(sp2));
     
    return
    100 == test5result(def) &&
    400 == test5result(sp1) &&
    0 == test5result(sp2) &&
    true;
    }
     
     
    //------------------------------------------------------------------------------
    int main() {
     
    bool ok =
    test1() &&
    #ifndef TYPE_CHECK_NO_VA_ARGS
    test2() &&
    #endif//TYPE_CHECK_NO_VA_ARGS
    test3() &&
    test4() &&
    test5() &&
    true;
     
    printf("\nAll tests passed: %s\n", strbool(ok));
     
    return ok ? EXIT_SUCCESS : EXIT_FAILURE;
    }
     
     
    // END MAIN.CPP

