Функция шаблона принимает вызываемые функторы с параметрами X

Я пишу размещенную на C ++ программу, которая запускает написанный пользователем C-код, скомпилированный на лету. Крайне важно, чтобы некоторые типичные исключения извлекались из C-кода и обрабатывались / игнорировались.
Чтобы сделать это, я вызываю код C из структурированного блока обработки исключений. Из-за природы и семантики этого блока (и откуда он вызывается) я отделил фактический вызов от его собственной функции:

    template <typename ret_type, class func>
static ret_type Cstate::RunProtectedCode(func function) {
ret_type ret = 0;
__try {
ret = function();
}
__except(ExceptionHandler(GetExceptionCode(), ExceptionStatus::CSubsystem)) {
fprintf(stderr, "First chance exception in C-code.\n");
}
return ret;
}

Который работает хорошо, как и должно быть так:

        RunProtectedCode<int>(entry);

Но возможно ли сформировать это так, чтобы я мог вызывать функции с переменным количеством параметров — может быть, путем некоторого использования экзотических функторов (очевидно, единственное требование — у него не может быть деструктора)? Я использую MSVC ++ 2010.

1

Решение

Если вы можете использовать C ++ 11, вы можете достичь этого с помощью вариативных шаблонов.

template <typename ret_type, class func, typename... Args>
static ret_type Cstate::RunProtectedCode(func function, Args... args) {
ret_type ret = 0;
__try {
ret = function(args...);
}
__except(ExceptionHandler(GetExceptionCode(), ExceptionStatus::CSubsystem)) {
fprintf(stderr, "First chance exception in C-code.\n");
}
return ret;
}

И вы можете назвать это как

RunProtectedCode<int>(entry2, 1, 2);
RunProtectedCode<int>(entry3, 1, "a", 3);

Вы можете упростить это (вид), используя вместо этого std :: function.

template <class func, typename... Args>
static
typename func::result_type Cstate::RunProtectedCode(func function, Args... args) {
typename func::result_type ret = typename func::result_type();
__try {
ret = function(args...);
}
__except(ExceptionHandler(GetExceptionCode(), ExceptionStatus::CSubsystem)) {
fprintf(stderr, "First chance exception in C-code.\n");
}
return ret;
}

И вы можете назвать это как

std::function<int(int,int,int)> entry_f = entry;
RunProtectedCode(entry_f,1,2,3);
2

Другие решения

Вы можете привязать все аргументы к вашей функции, что делает ее эффективным 0-арным функтором, например с помощью std::bind (доступно в VC2010) или boost::bind (Я предпочитаю этот, потому что реализация VC содержит сломанный std::cref). Привязка может быть выполнена в перегруженной функции до перехода к RunProtectedCodeнапример, что-то вроде этого:

template<typename R>
R(*f)() wrap(R(*f)())
{
return f;
}

template<typename R, typename A>
boost::function<R(A)> wrap(R(*f)(), A a)
{
return boost::bind(f, a);
}

template<typename R, typename A1, typename A2>
boost::function<R(A1, A2)> wrap(R(*f)(), A1 a1, A2 a2)
{
return boost::bind(f, a1, a2);
}
0

По вопросам рекламы [email protected]