В C++ функция с переменным числом аргументов шаблоны с переменным числом аргументов макроса



В настоящее время я работаю над проектом, в котором мне нужно упростить существующую систему.
Не вдаваясь в детали, проблема заключается в том, что я получаю некоторый указатель функции (от типа: void*), и мне нужно создать функцию из него (= create a function with signature). Так что мой подход заключался в том, чтобы создать следующий шаблон функции с переменным числом аргументов:



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);


Я получаю следующую ошибку: "описание кода серьезности ошибка состояния подавления строки файла проекта (Активный) неполный тип не допускается [...]главный.cpp 34 "



Итак, мой вопрос в том, что я делаю не так? Действительно ли проблема связана с парами в макросе 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) );
}


Определение этой функции:



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


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



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

606   1  

1 ответ:

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

#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* (или функции) являются первыми двумя параметрами. Далее следует список типов аргументов, заключенный в скобки, имена аргументов, заключенные также, и, наконец, заключенные типы и имена. Как я уже сказал, неуклюжий.

Это будет генерировать функцию:

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. Здесь элементы, разделенные запятыми и заключенные в скобки, являются одним макропараметром. На любом другом компиляторе это не сработало бы (что я знаю).

Comments

    Ничего не найдено.