C ++模板参数作为函数调用名称

时间:2016-10-16 16:32:59

标签: c++ c++11 templates variadic-templates

在C ++中,可以做出类似这样的事情:

class A 
{
public:
   template <typename ClassType, typename MethodName, typename ...Args>
   static func()
   {
       ClassType t = GetPtr<ClassType>();
       t->MethodName(GetArg<Args>()...);
   }
}

A::func<B, sum, double, double>(); //should call B->sum(double, double)
A::func<C, sum2, std::string, double, double>(); //should call C->sum2(std::string, double, double)

其中GetPtrGetArgs是从字典中获取指针的工作方法。

3 个答案:

答案 0 :(得分:3)

您可以使用非类型模板参数,例如:

template <typename ClassType, typename MethodType, MethodType MethodName, typename ...Args>
static void func() {
    ClassType t = GetPtr<ClassType>();
    (t->*MethodName)(GetArg<Args>()...);
}

使用它如下:

A::func<B, double (B::*)(double,double), &B::sum, double, double>();

当你的编译器支持c ++ 17时,你的代码甚至可以缩短:

template <typename ClassType, auto MethodName, typename ...Args>
static void func() {
    ClassType t = GetPtr<ClassType>();
    (t->*MethodName)(GetArg<Args>()...);
}

使用方法:

A::func<B, &B::sum, double, double>();

答案 1 :(得分:1)

不完全是你提出的问题,但我想你可以像

那样做
#include <array>
#include <vector>
#include <iostream>

template <typename Class, typename Method, typename ... Args>
void callMethod (Class & c, Method m, Args ... args)
 { ((&c)->*m)(args...); }

int main()
 {
   std::vector<int>     v;
   std::array<int, 5U>  a;

   callMethod(v, &std::vector<int>::size);
   callMethod(v, static_cast<void (std::vector<int>::*)(int const &)>
                    (&std::vector<int>::push_back), 7);
   callMethod(a, &std::array<int, 5U>::fill, 3);

   std::cout << v.back() << std::endl; // print "7"

   for ( auto const i : a )
      std::cout << i << std::endl; // print "3" five times
 }

使用push_back() std::vector<int>方法观察,需要演员(static_cast<void (std::vector<int>::*)(int const &)>)来解决重载歧义(push_back()中有两个std::vector<int>

不确定使用GetPtr()GetArgs(),但我想您可以使用callMethod(),如下所示

callMethod(GetPtr<B>(), &B::sum, GetArgs<double>(),
           GetArgs<double>());
callMethod(GetPtr<C>(), &C::sum2, GetArgs<std::string>(),
           GetArgs<double>(), GetArgs<double>());

答案 2 :(得分:1)

正如单词typename所暗示的那样,不,这不会起作用(通常),但是:

你基本上可以创建一个重载operator(.)的类,并在重载的运算符内进行调用。

事实上,Boost::bind正是如此,并且允许您获得可以在运行时作为对象传递的“仿函数”对象。