在我的引擎中,我有一个简单的反射系统,在编译时用类信息填充(也就是说,围绕一组模板构建,允许我自动化生成metainfo的过程)。
考虑以下例子:
class Type
{
//...
Map<PropertyHash, TypeProperty> _properties;
};对于每种类型,都有一个函数:
template <class T>
void InitializeType(TypeInitializer* typeInitializer);负责类型初始化。TypeInitializer几乎没有用于向类型添加字段和基类型的方法。因此,基本上,每一种新类型只需要这个函数的专门化。稍后,当首次查询类型时,TypeDatabase将创建具体的type对象,并为此调用InitializeType() (TypeInitializer在构造过程中得到指向类型的指针)。例如:
struct CST
{
const float* fptr;
volatile Uint32 vuint;
void** vptr;
};
template <>
SvrInline void InitializeType<CST>(TypeInitializer* typeInitializer)
{
typeInitializer->AddProperty("fptr", &CST::fptr);
typeInitializer->AddProperty("vuint", &CST::vuint);
typeInitializer->AddProperty("vptr", &CST::vptr);
}就是这样。所有魔术都是在TypeProperty构造函数中完成的,该构造函数声明为:
template <class Object_type, class Property_type>
TypeProperty(const char* fieldName, Property_type (Object_type::* propertyPtr));这使我能够知道财产的确切类型。我测试它的大小,控制度,易失性等,并将此信息保存在TypeProperty对象中。好的。
现在,我需要一些相同的东西,因为成员的功能以及。“‘Identical”的意思是,我可以以现在添加属性的方式添加函数。
我的第一个想法是各种模板(我的引擎构建时考虑到了对C++11特性的完全支持):
template <typename Object_t, typename Return_t, typename... Args>
TypeMethod(const char* methodName, Return_t (Object_t::*)(Args&&... args)
{
//What now?
}但是,我不知道如何从args中提取类型。我看到了一篇使用函数重载的方法的文章:
template <typename P, typename R, typename Arg1, typename... Args>
void Func(R (P::*)(Arg1 arg1, Args&&... args))
{
}
template <typename P, typename R, typename... Args>
void Func(R (P::*)(Args&&... args))
{
}
template <typename P, typename R>
void Func(R (P::*)())
{
}函数是递归地“转发”的(我知道这不是实际的递归),每次都少一个参数。不过,我看不出这适合我的情况。
发布于 2014-02-11 14:20:49
不需要递归,只需使用pack展开:
template <typename Object_t, typename Return_t, typename... Args>
TypeMethod(const char* methodName, Return_t (Object_t::*)(Args&&... args)
{
setName(methodName);
setObjectType<Object_t>();
setReturnType<Return_t>();
auto dummy[] = {0, (addArgumentType<Args>(), 0)...};
}我们将包扩展放在一个带括号的列表中,以确保对addArgumentType<...>的调用是按正确顺序进行的。
发布于 2014-02-11 14:10:21
...
template <typename P, typename R, typename Arg1, typename Arg2>
void Func(R (P::*)(Arg1 arg1, Arg2 arg2))
{
// function type is R (P::*)(Arg1 arg1, Arg2 arg2)
}
template <typename P, typename R, typename Arg1>
void Func(R (P::*)(Arg1 arg1))
{
// function type is R (P::*)(Arg1 arg1)
}
template <typename P, typename R>
void Func(R (P::*)())
{
// function type is R (P::*)()
}我不熟悉各种各样的args。这是C++11之前唯一的解决方案,但是现在C++11的新特性可以更好地解决这个问题。
顺便说一下。首先,我在boost.pyton库实现中看到了解析签名的方法。
发布于 2014-02-11 14:48:12
使用来自decompose_mem_fun_ptr的http://coliru.stacked-crooked.com/a/00750bf7564ab6d4
template <typename M>
TypeMethod(const char* methodName, M&m)
{
setName(methodName);
setObjectType<typename decompose_mem_fun_ptr<M>::class_type>();
setReturnType<typename decompose_mem_fun_ptr<M>::return_type>();
// use other info from decompose_mem_fun_ptr<M>.
using args_type = typename decompose_mem_fun_ptr<M>::arguments;
internal_setArgs<args_type>(make_index_sequence<std::tuple_size<args_type>::value>());
}
template<typename Tuple, std::size_t...Is>
void internal_setArgs(index_sequence<Is...>)
{
// Assuming setArg<T>(i_th).
int dummy[] = {0, (setArg<typename std::tuple_element<Is, Tuple>::type>(Is), 0)...};
static_cast<void>(dummy); // silent warning about unused variable.
}对于index_sequence和make_index_sequence
#if 1 // Not in C++11
#include <cstdint>
template <std::size_t ...> struct index_sequence {};
template <std::size_t N, std::size_t ...Is>
struct make_index_sequence : make_index_sequence < N - 1, N - 1, Is... > {};
template <std::size_t ... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
#endif // make_index_sequencehttps://stackoverflow.com/questions/21703821
复制相似问题