c++ - Variadic 模板候选者不匹配

标签 c++ templates metaprogramming variadic-templates

我正在尝试组合一个通用方法调用程序(用于 C++ OO/v8 桥),使用可变参数模板元编程构建参数列表,转换为 native 类型,最后执行附加方法,一旦传入参数列表为空(因此构建了传出):

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() 方法,以实际执行 native 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 值实际上并未作为参数传递 - 仅在模板中)。

但到目前为止,还没有骰子。任何人有任何其他想法,或者可以解释我要去哪里错了吗?

最佳答案

注意:

  • 您明确尝试调用模板
  • 您的模板化调用 始终需要将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>());
}

...如果没有您的用例的小型可编译示例(使用虚拟类型等),让它更接近您的代码会有点耗时。

关于c++ - Variadic 模板候选者不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9249337/

相关文章:

c++ - 如何将 3 个嵌套循环重写为一个循环?

python - 在 Python 中,如何获取成员函数的类名?

templates - Grails 布局可以调用模板吗?

c++ - 递归构造 unsigned int 的可变参数模板

python - 有没有办法为 Python 对象的所有成员打印简短版本的文档字符串?

python - boost::python 包装对象的 C++ 析构函数调用

c++ - 如何从 CopyDataStruct 中检索 vector ?

C++ std::cout 不向控制台写入任何内容

c++ - 模板化类的格式错误的非模板化方法的实例化

c++ - 将 int 映射到模板 int