mardi 31 mars 2020

Workaround for selecting template function implementation on MSVC++ 10.0

My purpose is to select different function implementation based on the memeber variable of data structure. I use member selection idiom "CREATE_MEMBER_DETECTOR" to detect if a data struct has certain member. In my case is to detect member base inside struct A_t and B_t (both of which has it) and member play_id inside base (A_t does not have play_id).The implementation below works on compiler MSVC++ 14.24. How can I make it work also on the old compiler MSVC++ 10.0, which yields tons of error on visual studio 2010.enter image description here

// templ_derive.h
#include <type_traits>

struct A_base_t {
    int id;
};
struct A_t {
    A_base_t base;

};

struct B_base_t {
    int play_id;
};
struct B_t {
    B_base_t base;
};

#define CREATE_MEMBER_DETECTOR(X)                                                   \
template<typename T> class Detect_##X {                                             \
    struct Fallback { int X; };                                                     \
    struct Derived : T, Fallback { };                                               \
                                                                                    \
    template<typename U, U> struct Check;                                           \
                                                                                    \
    typedef char ArrayOfOne[1];                                                     \
    typedef char ArrayOfTwo[2];                                                     \
                                                                                    \
    template<typename U> static ArrayOfOne & func(Check<int Fallback::*, &U::X> *); \
    template<typename U> static ArrayOfTwo & func(...);                             \
  public:                                                                           \
    typedef Detect_##X type;                                                        \
    enum { value = sizeof(func<Derived>(0)) == 2 };                                 \
};

CREATE_MEMBER_DETECTOR(base);
CREATE_MEMBER_DETECTOR(play_id);

template<typename T, bool>
struct use_base_s {
    static void valid(T data) {
        printf("bast t \n");
    }
};

template<typename T>
struct use_base_s <T, true> {

    static void valid(T data) {
        printf("no base t \n");
    }

    template<typename U = T>
    static void select_play_id(U data,
        typename std::enable_if<Detect_play_id<decltype(U::base)>::value,
        std::nullptr_t>::type = nullptr) {
        printf("has player_id t \n");
        return;
    }
    template<typename U = T>
    static void select_play_id(U data,
        typename std::enable_if<!Detect_play_id<decltype(U::base)>::value,
        std::nullptr_t>::type = nullptr) {
        printf("no player_id t \n");
        return;
    }
};

// main.cpp
#include "templ_derive.h"
int main() {
    A_t a_o = A_t();
    B_t b_o = B_t();
    use_base_s<A_t, Detect_base<A_t>::value>::select_play_id(a_o);
    use_base_s<B_t, Detect_base<B_t>::value>::select_play_id(b_o);
}

really appreciate Any help!

Aucun commentaire:

Enregistrer un commentaire