如何将宏生成的#foo 字符串传递到模板化的 class 中?
How to pass a macro-generated #foo string into a templated class?
我有一个宏:
#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 (...)
{
:
}
}
};
我想改进 std::cout 以便它输出 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(???)] );
...有什么办法让它起作用吗?
编辑:已解决
您可以这样做:
// 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 '[=10=]'
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<'[=10=]', 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 (`[=10=]` 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] : '[=10=]'; }
// 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) ? '[=10=]' : '[=10=]'>
您的代码变为:
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;
我有一个宏:
#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 (...)
{
:
}
}
};
我想改进 std::cout 以便它输出 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(???)] );
...有什么办法让它起作用吗?
编辑:已解决
您可以这样做:
// 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 '[=10=]'
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<'[=10=]', 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 (`[=10=]` 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] : '[=10=]'; }
// 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) ? '[=10=]' : '[=10=]'>
您的代码变为:
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;