将可变参数作为模板参数传递给函数的方法

4

假设有以下定义

struct Cla {
  void w(int x){}
};

template <typename C, void (C::*m)(int)> void callm(C *c, int args) {}


template <typename C, typename... A, void (C::*m)(A...)>
void callmv(C *c, A &&...args) {}

int main(){
  callm<Cla, &Cla::w>(&cla, 3);
  callmv<Cla, int, &Cla::w>(&cla, 3);
}

第一个函数(callm)没问题。但是第二个函数(callmv)无法编译,g++会给出以下错误信息:

test.cpp: In function ‘int main()’:
test.cpp:84:28: error: no matching function for call to ‘callmv<Cla, int, &Cla::w>(Cla*, int)’
   84 |   callmv<Cla, int, &Cla::w>(&cla, 3);
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
test.cpp:52:6: note: candidate: ‘template<class C, class ... A, void (C::* m)(A ...)> void callmv(C*, A&& ...)’
   52 | void callmv(C *c, A &&...args) {}
      |      ^~~~~~
test.cpp:52:6: note:   template argument deduction/substitution failed:
test.cpp:84:28: error: type/value mismatch at argument 2 in template parameter list for ‘template<class C, class ... A, void (C::* m)(A ...)> void callmv(C*, A&& ...)’
   84 |   callmv<Cla, int, &Cla::w>(&cla, 3);
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
test.cpp:84:28: note:   expected a type, got ‘&Cla::w’

什么是正确的语法?(我已经检查过将方法作为可变模板参数

你真的只能使用C++11吗?此外,你想将指针作为模板参数而不是函数参数的实际原因是什么? - user17732522
是的,我只能使用C++11。但如果不是这样,解决方案会是什么呢?原因是我需要保持与被调用函数相同的签名。 - Fabio Dalla Libera
1
使用C++17或更高版本,您可以将m作为auto非类型模板参数,并在模板中使用std::invoke。您不需要关心它的类型。 - user17732522
2
我认为在C++11中没有办法获得您建议的语法。您需要类似于callmv<Cla, decltype(&Cla::w), &Cla::w>(&cla, 3)(以及template <typename C, typename M, M m, typename... A>)这样的东西,尽管您可以摆脱第一个Cla。它可以从M中获取或者如果在列表中的M m之后,则可以从&cla中推断出来。 - user17732522
1个回答

2

可变参数包之后的所有参数都是始终推导的,不能显式地传递。 &Cla::w 被解释为参数包 A 中的下一个类型参数,而不是非类型模板参数。您得到的错误是编译器抱怨 &Cla::w 不是一种类型。

这意味着您必须首先传递成员函数。

template <typename M, M m, typename C, typename... A>
void callmv(C* c, A&&... args) {}

callmv<decltype(&Cla::w), &Cla::w>(&cla, 3);

另外,您可以将成员函数进行包装

template<typename F, typename... Args>
void callf(F f, Args&&... args)
{
    f(std::forward<Args>(args)...);
}

callf([](Cla* c, int i) { c->w(i); }, &c, 42);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接