C ++方法调用模板函数无法调用重载方法

时间:2010-10-19 01:43:10

标签: c++ templates generics function-pointers overloading

如果你有这个通用功能:

template<class type, class ret, class atype1, class atype2, class atype3>
ret call3(type *pClass, ret(type::* funcptr)(atype1, atype2, atype3), atype1 arg, atype2 arg2, atype3 arg3)
{
    //do some stuff here
    return (pClass->*funcptr)(arg, arg2, arg3);
}

你这样做:

class MyClass
{
  public: 
    void test(int, int, int){};
    void test(int, int){};
    void test(int, int, const char *){};  //comment this line, and it works fine.
};

...

    MyClass *a = new MyClass();
    call3(a, &MyClass::test, 1, 2, 3);

g ++会说:

no matching function for call to `call3(MyClass*&, <unknown type>, int, int, int)'

有什么方法可以解决这个问题吗? (我的代码可能非常糟糕,因为我不擅长C ++。)

5 个答案:

答案 0 :(得分:3)

您必须指定所需的三项测试中的哪一项。这可以通过演员来完成:

call3(a, static_cast<void (MyClass::*)(int, int, int)>(&MyClass::test), 1, 2, 3);

真的不是那么干净。给函数赋予不同的名称可能会更好。

答案 1 :(得分:3)

您可以明确指定要使用的模板。

call3<MyClass, void, int, int, int>( a, &MyClass::test, 1, 2, 3 );

如果重新排列模板参数的顺序,可以从参数中获取MyClass和void,因此需要重载时的调用将如下所示:

call3<int,int,int>( a, &MyClass::test, 1, 2, 3 )

请注意,当您实际上不需要显式重载解析时,它仍然可以

call3( a, &MyClass::otherfunction, 1,2,3 );

答案 2 :(得分:2)

原因是编译器有两个重载可供选择,每个重载都有三个参数。请注意,在参数推导过程中,编译器会从函数调用参数中推断出参与模板参数,并且不知不觉地查看参数/参数对。

只有在明确地查看每个参数/参数对确定模板参数时,参数推断才会成功。这意味着,在查看第二个参数/参数对时,它确实(并且不能)依赖于atype1,atype2和atype3都是'int'类型的事实,即使您将模板参数重新排列为

template<class type, class ret, class atype1, class atype2, class atype3> 
ret call3(type *pClass, atype1 arg, atype2 arg2, atype3 arg3, ret(type::* funcptr)(atype1, atype2, atype3)) 
{ 
    //do some stuff here 
    return (pClass->*funcptr)(arg, arg2, arg3); 
} 

以下是支持此标准的标准引用:

  

未推断的上下文是:

     

-   类型的嵌套名称说明符   是使用qualified-id指定的。

     

-   非类型模板参数或   数组绑定其中的子表达式   引用模板参数。

     

- A.   中使用的模板参数   函数参数的参数类型   它有一个默认参数   在呼叫中使用   论证推论正在进行中。

     

- A   函数参数为哪个参数   扣除不能做因为   关联函数参数是一个   函数或一组重载   函数(13.4),以及一个或多个   以下适用:

     

- 不止一个   函数匹配函数   参数类型(导致   模棱两可的扣除),或

     

- 没有功能   匹配函数参数类型,   或

     

- 提供的功能集   参数包含一个或多个   功能模板。

现在找到解决方案,

我认为唯一的解决方案是您必须明确指定模板参数,而不是依赖于模板参数推导。对模板参数进行一点重新安排将有助于

template<class atype1, class atype2, class atype3, class type, class ret> 
ret call3(type *pClass, ret(type::* funcptr)(atype1, atype2, atype3), atype1 arg, atype2 arg2, atype3 arg3) 
{ 
    //do some stuff here 
    return (pClass->*funcptr)(arg, arg2, arg3); 
} 

int main(){
    MyClass *a = new MyClass(); 
    call3<int, int, int>(a, &MyClass::test, 1, 2, 3); 
}

答案 3 :(得分:0)

编译器无法推断出返回参数类型。您必须明确指定call3的模板参数。

答案 4 :(得分:0)

我认为这里的问题是编译器无法解析您所指的test函数。

如果假设您有以下方法

void test(int, int, int);
void test(int, int, const char *); 

现在,如果你像这样打电话给test

test(1, 2, 3);

3可以隐式转换为const char *。因此编译器无法在函数test的两个重载之间解析,从而导致编译错误。

JoshD给出的解决方案应解决您的问题