将带有可变参数的模板函数分配给函数指针
Assignen a template function with Variadic arguments to a function pointer
在 C++ 中,我正在尝试制作采用第一个参数并对其调用方法的转发包装器。
这最终出现在给定代码中的 wrapper
方法中。这在调用时工作正常。
但是我想将这个模板化包装器分配给函数指针。在我的用例中,函数指针是给定的,我不能将它更改为 std::function
或类似的东西。这是因为它用在一个C的地方api.
我确实创建了以下示例:
#include <iostream>
template<auto FUNC, typename T, typename ... Params>
static auto wrapper(void* handle, Params&& ... args) {
auto* ser = static_cast<T*>(handle);
return (ser->*FUNC)(std::forward<Params>(args)...);
}
class MyTestClass {
public:
int method1(int i, int j) { return i + j; }
float method2(float f) {
return f * 2;
}
};
int main() {
MyTestClass thing{};
int (*serialize)(void* handle, int i, int j);
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
auto callMethod1Result = wrapper<&MyTestClass::method1, MyTestClass>(&thing, 1, 2);
std::cout << "callMethod1Result: " << callMethod1Result << std::endl;
return 0;
}
该方法的调用工作正常,但是:
int (*serialize)(void* handle, int i, int j);
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
不起作用,给我错误:
/.../temp.cpp:23:17: error: no matches converting function ‘wrapper’ to type ‘int (*)(void*, int, int)’
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/.../temp.cpp:4:13: note: candidate is: ‘template<auto FUNC, class T, class ... Params> auto wrapper(void*, Params&& ...)’
static auto wrapper(void* handle, Params&& ... args) {
^~~~~~~
经过一些尝试,我确实发现 Params&& ... args
部分导致了问题,因为如果我制作一个没有可变参数的更明确的包装器,那么它就可以工作。
我的主要问题是:我可以将带有可变参数的模板化方法分配给函数指针吗?如何分配?
问题是wrapper
将args
作为转发引用,它的类型总是引用:左值引用或右值引用。但是serialize
被声明为i
和j
取值int
的函数指针,它们不能匹配引用类型,这使得[=上的模板参数推导18=] 在 serialize = wrapper<&MyTestClass::method1, MyTestClass>;
中失败。
您可以通过在 serialize
.
的声明中更改 i
和 j
的类型来修复它
例如
int (*serialize)(void* handle, int&& i, int&& j);
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
或者改变wrapper
取args
值。
例如
template<auto FUNC, typename T, typename ... Params>
static auto wrapper(void* handle, Params ... args)
在 C++ 中,我正在尝试制作采用第一个参数并对其调用方法的转发包装器。
这最终出现在给定代码中的 wrapper
方法中。这在调用时工作正常。
但是我想将这个模板化包装器分配给函数指针。在我的用例中,函数指针是给定的,我不能将它更改为 std::function
或类似的东西。这是因为它用在一个C的地方api.
我确实创建了以下示例:
#include <iostream>
template<auto FUNC, typename T, typename ... Params>
static auto wrapper(void* handle, Params&& ... args) {
auto* ser = static_cast<T*>(handle);
return (ser->*FUNC)(std::forward<Params>(args)...);
}
class MyTestClass {
public:
int method1(int i, int j) { return i + j; }
float method2(float f) {
return f * 2;
}
};
int main() {
MyTestClass thing{};
int (*serialize)(void* handle, int i, int j);
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
auto callMethod1Result = wrapper<&MyTestClass::method1, MyTestClass>(&thing, 1, 2);
std::cout << "callMethod1Result: " << callMethod1Result << std::endl;
return 0;
}
该方法的调用工作正常,但是:
int (*serialize)(void* handle, int i, int j);
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
不起作用,给我错误:
/.../temp.cpp:23:17: error: no matches converting function ‘wrapper’ to type ‘int (*)(void*, int, int)’
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/.../temp.cpp:4:13: note: candidate is: ‘template<auto FUNC, class T, class ... Params> auto wrapper(void*, Params&& ...)’
static auto wrapper(void* handle, Params&& ... args) {
^~~~~~~
经过一些尝试,我确实发现 Params&& ... args
部分导致了问题,因为如果我制作一个没有可变参数的更明确的包装器,那么它就可以工作。
我的主要问题是:我可以将带有可变参数的模板化方法分配给函数指针吗?如何分配?
问题是wrapper
将args
作为转发引用,它的类型总是引用:左值引用或右值引用。但是serialize
被声明为i
和j
取值int
的函数指针,它们不能匹配引用类型,这使得[=上的模板参数推导18=] 在 serialize = wrapper<&MyTestClass::method1, MyTestClass>;
中失败。
您可以通过在 serialize
.
i
和 j
的类型来修复它
例如
int (*serialize)(void* handle, int&& i, int&& j);
serialize = wrapper<&MyTestClass::method1, MyTestClass>;
或者改变wrapper
取args
值。
例如
template<auto FUNC, typename T, typename ... Params>
static auto wrapper(void* handle, Params ... args)