我正在尝试将通用方法调用程序(用于C ++ OO / v8桥)放在一起,使用可变参数模板元编程来构建参数列表,转换为本机类型,最后执行附加方法,一旦传入参数list为空(因此构建了传出):
template<typename... PARAMS>
class InvocationBuilder {
public:
void invoke(const Arguments &source, PARAMS&... params) {
cout << "Invoke" << endl;
(instance->*(method))(*params...);
}
template<class HEAD, class ... TAIL>
void invoke(const Arguments &source, PARAMS... params) {
cout << "Expand" << endl;
Type<HEAD> param(source[sizeof...(PARAMS)]);
InvocationBuilder<PARAMS..., HEAD> builder;
builder.template invoke<TAIL...>(source, params..., *param);
}
Type类只是一个包装器,用于创建v8参数的堆栈范围变体(例如,在调用期间,可以在范围内使用char *字符串,但在调用返回后会自动清除)。
现在,当实际桥接器使用参数列表调用它时,使用:
InvocationBuilder<> builder;
builder.template invoke<ARGS...>(args);
其中args是v8 :: Arguments引用。
编译器正确链接参数生成的每一步,但无法与非模板化的invoke()方法匹配,以实际执行本机C ++方法。
错误消息如下:
include/link/function.hh: In member function 'void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder<PARAMS>::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = int, TAIL = {}, PARAMS = {int, int}, CLASS = SomeClass, ARGS = {int, int, int}]':
include/link/function.hh:65:6: recursively instantiated from 'void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder<PARAMS>::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = int, TAIL = {int}, PARAMS = {int}, CLASS = SomeClass, ARGS = {int, int, int}]'
include/link/function.hh:65:6: instantiated from 'void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder<PARAMS>::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = int, TAIL = {int, int}, PARAMS = {}, CLASS = SomeClass, ARGS = {int, int, int}]'
include/link/function.hh:47:5: instantiated from 'v8::Handle<v8::Value> sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::run(const v8::Arguments&) [with CLASS = SomeClass, ARGS = {int, int, int}]'
test.cc:41:1: instantiated from here
include/link/function.hh:65:6: error: no matching function for call to 'sjs::link::InstanceFunctionVariadic<SomeClass, int, int, int>::InvocationBuilder<int, int, int>::invoke(const v8::Arguments&, int&, int&, int)'
include/link/function.hh:65:6: note: candidate is:
include/link/function.hh:61:10: note: template<class HEAD, class ... TAIL> void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = HEAD, TAIL = {TAIL ...}, PARAMS = {int, int, int}, CLASS = SomeClass, ARGS = {int, int, int}]
该消息清楚地表明,对于C ++实例方法void test(int a,int b,int c),前三个步骤正常工作,使用Type提取参数并传递结果 - 但我可以'弄清楚为什么没有正确使用最终的invoke()。
我试图完全专门化它,但后来我收到有关命名空间范围之外的特殊化的错误消息(我假设是因为该方法是模板化类的成员)。
我还尝试转移传入/传出参数列表,以便传入的是类可变参数模板,而传入方法专门用于调用类 - 但我遇到了“对不起,未实现“关于将可变参数解压缩到静态模板中的消息。
我也试过通过使用通用单个可变参数模板,然后专门用于HEAD / TAIL情况,并专门针对空集案例,但后来我立即产生歧义(可能是因为HEAD / TAIL值)实际上并不作为参数传递 - 仅在模板中传递。
但到目前为止,没有骰子。任何人都有其他想法,或者可以解释我哪里出错了?
答案 0 :(得分:1)
请注意:
invoke
始终要求PARAMS...
作为函数参数传递一种可能的选择:
#include <functional>
template<class... Types> struct List {};
template<class... PARAMS> struct Invoker {
typedef std::function<void (PARAMS&...)> Fn;
Fn fn_;
Invoker(const Fn&& fn) : fn_(fn) {}
void invoke(List<>, PARAMS&... params) {
fn_(params...);
}
template<class HEAD, class... TAIL, class... ARGS>
void invoke(List<HEAD, TAIL...>, ARGS... params) {
HEAD param; // or your Type<HEAD> ... etc.
invoke(List<TAIL...>(), params..., param);
}
};
void f(int, int, int) {} // some function you want to call
int main() {
Invoker<int,int,int> inv(&f);
inv.invoke(List<int,int,int>());
}
...如果没有一个小的可编辑的用例示例(使用虚拟类型等),那么将这些代码与您的代码更紧密地匹配将会有点费时。