2016-02-16 6 views
3

В настоящее время я работаю над проектом, где мне нужно упростить существующую систему. Wihtout, вдаваясь в подробности, проблема в том, что я получаю некоторый указатель на функцию (от типа: void *), и мне нужно создать из нее функцию (= создать функцию с сигнатурой). Таким образом, мой подход заключается в создании следующей VARIADIC функции шаблона:C++ variadic templates function in variadic macro

template <typename ReturnType, typename ... Params> 
ReturnType(*GetFunction(void* func, Params ...)) (Params ...) 
{ 
    return reinterpret_cast<ReturnType(*) (Params ...)> (func); 
} 

Теперь мне нужен способ, чтобы создать необходимые функции:

#define DECLARE_PARAMS(...) __VA_ARGS__ 

#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params)\ 
{\ 
    return FUNCTION_DIRECTCALL(returnType, fname, (DECLARE_PARAMS Params));\ 
} 

и здесь проблема. (Я думаю) Парамы не расширяют способ расширения. Но я не знаю почему?

Я тестировал FUNCTION_DIRECTCALL в DEFINE_FUNCTION макро с закодированных значений (просто положить дефиниция в DirectCall), и она работала так, что не должно быть ошибки, но я открыт для улучшения

#define FUNCTION_DIRECTCALL(returnType, functionName, ...) \ 
GetFunction<returnType>(functionName, DECLARE_PARAMS __VA_ARGS__) (DECLARE_PARAMS __VA_ARGS__) 

Если Я стараюсь, чтобы определить функцию с макро

Define_Function(void, ThatFunction, (int a_, int b_)); // void ThatFunction(int a, int b); 

я получаю следующее сообщение об ошибке: «Тяжесть Код Описание проекта Строка файла Подавление состояние ошибки (активный) неполный тип не допускается [...] \ main.cpp 34 "

Итак, мой вопрос: что я делаю неправильно? Действительно ли проблема связана с Params в макросе DEFINE_FUNCTION или я что-то пропустил?

Я работал с макросами, но я бы не стал называть себя экспертом в этой области. Но, как я понимаю, что (DECLARE_PARAMS Params) следует расширить Params в:

int a_, int b_ 

и после сканирования я ожидал бы следующий код:

void Gen_ThatFunction(int a_, int b_) 
{ 
    return GetFunction<void>(ThatFunction, a_, b_) (a_, b_); 
} 

Тестирование макроса DirectCall: с следующий код я проверил функциональность DirectCall макро

Поэтому я изменить Define_Function макро:

#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params) \ 
{\ 
    int a = 2, b = 3;\ 
    return FUNCTION_DIRECTCALL(void, ThatFunction, (a, b));\ 
} 

Определение ThatFunction:

void ThatFunction(int a, int b) 
{ 
    std::cout << a << " * " << b << " = " << b * a << std::endl; 
} 

выход: "2 * 3 = 6"

Весь код скомпилирован в VC++ 2015

+0

Вы уверены, что это не должно быть 'DECLARE_PARAMS (Params)'? – Claudiu

+0

Я вообще не вижу смысла 'DECLARE_PARAMS'. Просто возьмите многоточие и используйте '__VA_ARGS__'. Не нужно пересылать его через другой макрос. – chris

+0

@chris в этом контексте пересылка не имеет смысла. Но это необходимо для внутреннего использования (позже). – MainCPP

ответ

0

Единственный способ я знаю, как сделать то, что вы прошу действительно неуклюже.

#define DEFINE_FUNCTION(RET, NAME, TYPES, NAMES, BOTH) RET Gen_##NAME BOTH { return reinterpret_cast<RET(*)TYPES>(NAME) NAMES; } 

Вы можете использовать его как:

DEFINE_FUNCTION(void, ThatFunction, (int, int), (a_, b_), (int a_, int b_)) 

Возвращаемый тип и имя (или функции) void* первые два параметра. Далее приведен список типов аргументов, заключенных в круглые скобки, имена аргументов, заключенные также, и, наконец, имена закрытых типов AND. Как я и сказал, неуклюже.

Это создаст функцию:

void Gen_ThatFunction (int a_, int b_) { return reinterpret_cast<void(*)(int, int)>(ThatFunction) (a_, b_); } 

Вы можете вызвать функцию, как вы хотите:

Gen_ThatFunction(2, 3); //prints "2 * 3 = 6" 

Конечно, имейте в виду, что это Microsoft специфичны. Здесь разделенные запятыми элементы, заключенные в скобки, являются одним параметром макроса. На любом другом компиляторе это не сработает (что я знаю).

+0

Это было мое первое решение этой проблемы. Но клиент хочет более «интуитивно понятное» решение. Если вы посмотрите на DEFINE_FUNCTION, вы увидите, что макрос выглядит точно так же, как объявление функции. И это то, что я хочу достичь, не развивая целую систему рефлексии. – MainCPP

+0

@MainCPP У функций есть перегрузки? Если есть только одна «Gen_ThatFunction», вы можете сделать ссылку на шаблон вариационной функции. В противном случае, я думаю, вы можете использовать только вариационную функцию и просто не иметь список видимых наборов аргументов. –

+0

да, это их перегрузки. В настоящее время я решил проблему, просто используя фиксированное количество макросов параметров (DECLARE_FUNCTION_ONE_PARAM), Params меня разделяет запятой, поэтому проблема решена. Я приму свой ответ, потому что это решение для описанной проблемы. – MainCPP