В моем движке у меня есть простая система отражения, заполненная информацией о классах во время компиляции (т. Е. Построенная вокруг набора шаблонов, что позволяет мне автоматизировать процесс генерации метаинфо).Как передать произвольную функцию-член ЛЮБОГО класса в шаблон, чтобы разрешить его подпись?
Рассмотрим следующий пример:
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. Ницца.
Теперь мне нужно что-то идентичное для функции членов. «Идентичный» означает, что я могу добавить функцию так же, как сейчас добавляю свойства.
Моя первая мысль была VARIADIC шаблоны (мой двигатель построен с полной поддержкой C++ 11 функций в виду):
template <typename Object_t, typename Return_t, typename... Args>
TypeMethod(const char* methodName, Return_t (Object_t::*)(Args&&... args)
{
//What now?
}
я не знаю, однако, как я должен извлечь из типов арг. Я видел статью с подходом, который использует перегрузку функции:
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::*)())
{
}
Функция была «пересылается» рекурсивно (я знаю, что это не фактическая рекурсия) с одним параметром меньше каждый раз. Однако я не вижу, как это подходит для моего дела.
Найдено в [Accept-любой-вид-на-вызываемая-и-и-ноу-аргумент типа] (http://stackoverflow.com/questions/21465394/accept-any-kind-of-callable-and-also-know-argument-type/21466644#comment32402978_21466644), http://coliru.stacked-crooked.com/a/00750bf7564ab6d4 тоже может помочь. – Jarod42
Спасибо за этот чрезвычайно полезный ресурс! –