向模板类传递通用方法的指针。

问题描述 投票:0回答:1

我想做一个模板类,它的构造函数接受一个对象指针和一个指向对象的一个方法的指针。模板类必须接受一个带有任何参数的方法,所以我认为方法的类型应该是一个模板参数。我也希望接受一个具有任何返回类型的方法,但约束它返回void也可以。下面的代码无法编译。正确的语法是什么?

template <typename Obj, typename Method>
class Foo
{
public:
  Foo(Obj *obj, Obj::*Method method)
    :mObj(obj), mMethod(method)
  {}

  void callMethod()
  {
    mObj->mMethod();
  }

private:
  Obj* mObj;
  Obj::*Method mMethod;
};

class Bar
{
public:
  // I want it to work no matter what arguments this method takes.
  void method() {}
};

Bar bar;
Foo <Bar, void(Bar::*)()> foo(&bar, &Bar::method);

我在Foo构造函数中得到这个错误。

error C2059: syntax error: '<tag>::*'

我的... 前一个问题 在这个主题上的文章被标记为重复,但所引用的例子指定了可以传递的方法的确切类型,而我需要它是通用的。

c++ templates
1个回答
2
投票

首先,你的代码中存在几个语法问题。另外,你不需要 Method 作为模板参数,因为你总是希望传递一个由 Object 类型。

要把可变数量的参数放入 callMethod,只需提供一个变量参数包给 Foo. 此外,您还可以推断出该公司的回报类型。callMethod 函数。

把所有这些放在一起,你可以得到。

template <typename Obj, typename Ret, typename ...Args>
class Foo
{
public:
  Foo(Obj *obj, Ret (Obj::*method)(Args...))
    : mObj(obj), mMethod(method)
  {}

  Ret callMethod(Args... args)
  {
    return (mObj->*mMethod)(args...);
  }

private:
  Obj* mObj;
  Ret (Obj::*mMethod)(Args...);  // this is essentially 'Method'
};

现在,如果你的类中有一个特定函数的参数数是可变的,它就能正常工作。

class Bar
{
public:
  void method() { std::cout << "bar"; }
};

class Car
{
public:
  int method2(int, double) { 
    std::cout << "car"; 
    return 42;
   }
};

int main()
{
Bar bar;
Car car;
Foo a (&bar, &Bar::method);
Foo b (&car, &Car::method2);
a.callMethod();  // prints 'bar'
b.callMethod(5, 3.2);  // prints 'car'
}

下面是一个工作原理 演示.

请注意,在实际的解决方案中,你可能希望完美转发参数,但这应该让你走上正确的轨道。

另外,在c++17之前,没有CTAD(类模板参数推导),所以你必须在构造时指定模板参数 Foo 对象,像这样。

Foo <Bar, void> a(&bar, &Bar::method);
Foo <Car, int, int, double> b(&car, &Car::method2);
© www.soinside.com 2019 - 2024. All rights reserved.