C++ Metaprogramming Tricks

Check that static method exists

struct SOME_STRUCT {
    static int doIt(int a, float b) {
        return 0;
    }
};

template<typename T> struct HAS_DO_IT {

    static int has(int (*doIt)(int, float)) {}
    static char has(...) {}

    static const int value = sizeof(decltype(has(T::doIt))) == sizeof(int);
};

TEST_CASE("A") {
    printf("%d", HAS_DO_IT<SOME_STRUCT>::value);
}

Things to remember for template type deduction

template<typename  T> struct DEDUCTED_TYPE {
    typedef T type;
};

TEST_CASE("Type Deduction") {
    // i
    std::cout << typeid(DEDUCTED_TYPE<int>::type).name() << std::endl;
    // Pi
    std::cout << typeid(DEDUCTED_TYPE<int*>::type).name() << std::endl;
    // i
    std::cout << typeid(DEDUCTED_TYPE<int&>::type).name() << std::endl;
    // i
    std::cout << typeid(DEDUCTED_TYPE<const int>::type).name() << std::endl;
    // PKI
    std::cout << typeid(DEDUCTED_TYPE<const int*>::type).name() << std::endl;
    // i
    std::cout << typeid(DEDUCTED_TYPE<const int&>::type).name() << std::endl;
    // i
    std::cout << typeid(DEDUCTED_TYPE<volatile const int>::type).name() << std::endl;
    // PVKi
    std::cout << typeid(DEDUCTED_TYPE<volatile const int*>::type).name() << std::endl;
    // i
    std::cout << typeid(DEDUCTED_TYPE<volatile const int&>::type).name() << std::endl;
    // i
    std::cout << typeid(DEDUCTED_TYPE<volatile const int&&>::type).name() << std::endl;

}

Template Class Members

struct Bla {
    int id;
};

template<typename M, M member, typename T>
struct MemberSetter1 {
    using type = typename std::decay<decltype(T{}.*member)>::type;
    template<class C, typename Z>
    static Z* getPointerType(Z C::*v){return 0;}
    using member_type = typename        
        std::decay<decltype(getPointerType(member))>::type;

    static void set(T &t, type value) {
        t.*member = value;
    }

    static type get(T &t) {
        return t.*member;
    }
};


TEST_CASE("BIND_TAG_#1") {
    Bla b;
    // Here template types get deduced to:
    //  M = int Bla::*
    //  member = &Bla::id
    // MemberSetter::member_type becomes int, first way to obtain member type
    // MemberSetter::type becomes int, second way to obtain member type
    MemberSetter1<decltype(&Bla::id), &Bla::id, Bla> bind;
    bind.set(b, 1);
    std::cout << bind.get(b) << std::endl;
}

Deducing Function Argument Type

        template <typename A>
        static A* deduceType(Result<bool> (*)(A&, ConstBufferIterator)) {return 0;}
        using argument_type = typename     
        std::remove_pointer<decltype(deduceType(Class::static_method))>::type;

Feature Flags

enum class FF {
    A, B, C
};

template<bool v, FF a, FF b, FF ... rem>
struct _$_HasFF : _$_HasFF<v || a == b, a, rem...> {

};

template<bool v, FF a, FF b>
struct _$_HasFF<v, a, b>  {
    static const bool value = v || a == b;
};

template <FF a, FF...rem>
struct HasFF : _$_HasFF<false, a, rem...>{

};

TEST_CASE("Feature Flags") {
    std::cout << HasFF<FF::C, FF::A, FF::B>::value << std::endl;
}

Iterating over variadic template arguments in function

      template<size_t L,size_t i, typename BINDING, typename ... REMAINING_BINDINGS>
        static typename std::enable_if<i < L, bool>::type requiredBindingsAreSet(bool (&fields)[L]) {
            if(L == i) {
                return true;
            } else if(!fields[i] && BINDING::isRequired)
                return false;
            else
                requiredBindingsAreSet<L, i+1, REMAINING_BINDINGS...>(fields);
        }

        template<size_t L,size_t i>
        static typename std::enable_if<L == i, bool>::type requiredBindingsAreSet(bool (&fields)[L]) {
            return true;
        }

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *