Как создать шаблон параметра в указателе функции? - PullRequest
2 голосов
/ 04 мая 2020

У меня есть шаблон:

template<typename T>
void testFuction(int(*testFunc)(CallBack, void *, T *))
{
    // define CallBack callback, void* param1, T* param2
    // ...
    testFunc(callback, param1, param2);
}

Это работает, но выглядит ужасно, я хочу сделать что-то вроде:

template<typename T>
// using TestFunc<T> = std::function<int(CallBack, void *, T *)>
void testFuction(TestFunc<T> testFunc)
{
   // define CallBack callback, void* param1, T* param2
   // ...
   testFunc(callback, param1, param2);
}

Но это не работает.

Может ли кто-нибудь помочь мне с этим? Я также перегружаю многие подобные функции некоторыми добавленными параметрами, и они выглядят ужасно. Я хочу определить TestFunc<T> один раз и использовать его снова в функциях шаблона.

Ответы [ 2 ]

3 голосов
/ 04 мая 2020

Вы можете предоставить псевдоним типа для шаблонного указателя функции следующим образом

#include <utility> // std::forward

template<typename T>
using FunPointerT = int(*)(CallBack, void*, T*);

template<typename T, typename... Args>
void testFuction(FunPointerT<T> funcPtr, Args&& ...args)
{
   // variadic args, in the case of passing args to testFuction
   funcPtr(std::forward<Arg>(args)...);
}

Обновление в соответствии с требованием Оператора

template<typename T> 
void testFuction(FunPointerT<T> funcPtr) 
{
   // ...
   funcPtr(/* args from local function scope */);
}
1 голос
/ 04 мая 2020

Давайте рассмотрим упрощенный пример:

#include <functional>

template<typename T>
void test_function(std::function<void(T*)> f) {
    f(nullptr);
}

void use_int_ptr(int* i);

int main() {
    test_function(use_int_ptr);
}

, который не компилируется: T не может быть выведено как int. Причина, по которой он работает с void (*f)(T*), заключается в том, что T можно вывести , если передать указатель на функцию, но указатель на функцию не является std::function.

У вас есть несколько возможные решения. Вы можете вручную указать T:

test_function<int>(use_int_ptr);

Вместо этого можно передать std::function, чтобы можно было вывести T:

test_function(std::function<void(int*)>{use_int_ptr});
// Or in C++17 with CTAD
test_function(std::function{use_int_ptr});

Создать функцию пересылки, которая переносит функцию указатели в std::function с, как указано выше, необходимо вручную передать std::function с для других вызываемых объектов:

template<typename T>
void test_function(void f(T*)) {
    test_function(std::function<void(T*)>{f});
}

или просто взять любой тип в исходной функции:

template<typename F>
void test_function(F&& f) {
    f(nullptr);
}
...