2015-01-12 60 views
0

我有一個宏:如何將宏生成的#foo字符串傳遞給模板類?

#define BIND(c_slot, cxx_target) c_slot = & Generate< 
                decltype(c_slot) 
                , decltype(&cxx_target) 
                , &cxx_target 
              >::call; 

我會用這樣的:

BIND(table->fooslot , Base::foofunc); 

Generate看起來是這樣的:

template<typename Fc, typename Target, Target target> 
struct Generate; 

template < typename R  , typename ...Arg  , 
      typename RTarg , typename ...TargArg , 
              RTarg(ExtObjBase_noTemplate::*target)(TargArg...) > 
struct Generate< R(*)(PyObject*, Arg...), RTarg(ExtObjBase_noTemplate::*  )(TargArg...), target > 
{ 
    static R call(PyObject* self, Arg... carg) 
    { 
     std::cout << "SLOT!" << std::endl; 
     try 
     { 
      RTarg r_cxx = (cxxbase_for(self)->*target) (Convert<Arg>::to_cxx(carg) ...); 
      return Convert<RTarg>::to_c(r_cxx); 
     } 
     catch (...) 
     { 
      : 
     } 
    } 
}; 

我想改善的是性病::法院以便輸出WHICH槽。

喜歡的東西:

#define BIND(c_slot, cxx_target) c_slot = & Generate< 
                decltype(c_slot) 
                , decltype(&cxx_target) 
                , &cxx_target 
                , #c_slot 
              >::call; 

但我無法弄清楚如何使它發揮作用。

有沒有辦法做到這一點?

編輯:一個可能的辦法是有:

static std::map<void*, std::string> names_map; 

: 

#define BIND(c_slot, cxx_target) \ 
    c_slot = & Generate< decltype(c_slot) ,decltype(&cxx_target), &cxx_target >::call; \ 
    names_map[offset_of(&cxx_target)] = std::string(#c_slot); 

: 

template <STUFF> 
struct Generate<STUFF> 
{ 
    static R call(STUFF) 
    { 
     COUT("SLOT: " << names_map[offset_of(???)]); 

...有沒有辦法讓工作?

編輯:這已經解決here

+1

字符串常量不能做模板a因此你必須使用一些二進制遞歸宏將它分成合理數量的字符。 – Columbo

回答

1

你可以這樣做:

// Sequence of char 
template <char...Cs> struct char_sequence 
{ 
    template <char C> using push_back = char_sequence<Cs..., C>; 
}; 

// Remove all chars from char_sequence from '\0' 
template <typename, char...> struct strip_sequence; 

template <char...Cs> 
struct strip_sequence<char_sequence<>, Cs...> 
{ 
    using type = char_sequence<Cs...>; 
}; 

template <char...Cs, char...Cs2> 
struct strip_sequence<char_sequence<'\0', Cs...>, Cs2...> 
{ 
    using type = char_sequence<Cs2...>; 
}; 

template <char...Cs, char C, char...Cs2> 
struct strip_sequence<char_sequence<C, Cs...>, Cs2...> 
{ 
    using type = typename strip_sequence<char_sequence<Cs...>, Cs2..., C>::type; 
}; 

// helper to get the i_th character (`\0` for out of bound) 
template <std::size_t I, std::size_t N> 
constexpr char at(const char (&a)[N]) { return I < N ? a[I] : '\0'; } 

// helper to check if the c-string will not be truncated 
template <std::size_t max_size, std::size_t N> 
constexpr bool check_size(const char (&)[N]) 
{ 
    static_assert(N <= max_size, "string too long"); 
    return N <= max_size; 
} 

// Helper macros to build char_sequence from c-string 
#define PUSH_BACK_8(S, I) \ 
    ::push_back<at<(I) + 0>(S)>::push_back<at<(I) + 1>(S)> \ 
    ::push_back<at<(I) + 2>(S)>::push_back<at<(I) + 3>(S)> \ 
    ::push_back<at<(I) + 4>(S)>::push_back<at<(I) + 5>(S)> \ 
    ::push_back<at<(I) + 6>(S)>::push_back<at<(I) + 7>(S)> 

#define PUSH_BACK_32(S, I) \ 
     PUSH_BACK_8(S, (I) + 0) PUSH_BACK_8(S, (I) + 8) \ 
     PUSH_BACK_8(S, (I) + 16) PUSH_BACK_8(S, (I) + 24) 

#define PUSH_BACK_128(S, I) \ 
    PUSH_BACK_32(S, (I) + 0) PUSH_BACK_32(S, (I) + 32) \ 
    PUSH_BACK_32(S, (I) + 64) PUSH_BACK_32(S, (I) + 96) 

// Macro to create char_sequence from c-string (limited to 128 chars) 
#define MAKE_CHAR_SEQUENCE(S) \ 
    strip_sequence<char_sequence<> \ 
    PUSH_BACK_128(S, 0) \ 
    >::type::template push_back<check_size<128>(S) ? '\0' : '\0'> 

並且代碼:

template<typename Fc, typename Target, Target target, typename CharSeq> 
struct Generate; 

template < typename R  , typename ...Arg  , 
      typename RTarg , typename ...TargArg , 
      RTarg(ExtObjBase_noTemplate::*target)(TargArg...) , 
      char...Cs> 
struct Generate< R(*)(PyObject*, Arg...), RTarg(ExtObjBase_noTemplate::*  )(TargArg...), target , char_sequance<Cs...>> 
{ 
    static R call(PyObject* self, Arg... carg) 
    { 
     const char name[] = {Cs...}; 
     std::cout << name << std::endl; 
     try 
     { 
      RTarg r_cxx = (cxxbase_for(self)->*target) (Convert<Arg>::to_cxx(carg) ...); 
      return Convert<RTarg>::to_c(r_cxx); 
     } 
     catch (...) 
     { 

     } 
    } 
}; 

而且

#define BIND(c_slot, cxx_target) c_slot = & Generate< 
               decltype(c_slot) 
               , decltype(&cxx_target) 
               , &cxx_target, 
               MAKE_CHAR_SEQUENCE(#c_slot) 
             >::call; 
相關問題