编译有关c ++模板推导的错误

时间:2018-03-14 11:56:38

标签: c++ templates template-deduction

#include <iostream>

template <int N>                                                                         
class X {
public:
  using I = int;                                                                         
  void f(I i) {
    std::cout << "i: " << i << std::endl;
  }
};

template <int N>
void fppm(void (X<N>::*p)(typename X<N>::I)) {
  p(0);
}

int main() {
  fppm(&X<33>::f); 
  return 0;
}

我只是不理解代码的编译错误消息。

error: called object type 'void (X<33>::*)(typename X<33>::I)' is not a function or function pointer
 p(0);

我认为p是一个返回void的函数,并以int为参数。但显然,事实并非如此。有人能给我线索吗?

2 个答案:

答案 0 :(得分:3)

由于p是指向非静态成员函数的指针,因此您需要一个实例来调用它。因此,首先在main中实例化X<33>的对象:

int main() {
  X<33> x;
  fppm(x, &X<33>::f); // <-- Signature changed below to accept an instance

然后在您的函数中,更改代码以接受X<N>的实例并为其调用成员函数:

template <int N>
void fppm(X<N> instance, void (X<N>::*p)(typename X<N>::I)) {
  (instance.*p)(0);
}

语法可能看起来很难看,但是指向成员运算符的指针的低优先级需要括号。

答案 1 :(得分:2)

如评论中所述,p是指向成员函数的指针,但您将其称为静态函数(p(0);)。您需要一个具体对象来呼叫p

X<N> x;
(x.*p)(0);
// or:
X<N>* xx = new X<N>();
(xx->*p)(0);
delete xx;

请注意.* / ->*运算符的优先级低于函数调用运算符,因此需要括号。

旁注:以上是为了更好地说明,现代C ++可能会使用auto关键字和智能指针,它们可能如下所示:

auto x = std::make_unique<X<N>>();
(x.get()->*p)(0);