可变参数模板参数顺序问题

时间:2019-02-21 18:45:47

标签: c++ templates variadic-templates c++03 template-deduction

我有一个模板化的函数包装器,我试图将其更新为C ++ 11语法(可变参数)。

我的问题是我被困在“ catch 22”中,其中“ Args...”必须是最后一个模板参数,但同时不能在函数指针模板参数之后定义。

知道这是否可以解决吗?

  template <typename... Args, void(*Function)(Args...)>
  class function
  {
  public:

    void operator ()(Args... args) const
    {
      (*Function)(std::forward<Args...>(args...));
    }
  };

1 个答案:

答案 0 :(得分:0)

一种可能的方法是使用模板专业化

template <typename>
struct myFunc;

template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
 {
   // ...
 };

但是,通过这种方式,您拦截(作为模板参数)功能指针的类型,而不是功能指针本身;因此您必须以某种方式传递函数指针(构造函数?)。

还要注意,如果要使用完美的转发,则必须在接收自变量作为通用引用(operator())的模板方法中转换&&

以下内容

   template <typename ... As>
   R operator() (As && ... args) const
    {
      return fun(std::forward<As>(args)...);
    }

其中fun是类型R(*)(Args...)的指针。

以下是完整的编译示例

#include <iostream>
#include <utility>

int foo (int, long)
 { return 42; }

template <typename>
struct myFunc;

template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
 {
   using  funPnt = R(*)(Args...);

   funPnt  fun = nullptr;

   myFunc (funPnt f0) : fun{f0}
    { }

   template <typename ... As>
   R operator() (As && ... args) const
    {
      return fun(std::forward<As>(args)...);
    }
 };

int main ()
 { 
   myFunc<decltype(&foo)>  mf0{&foo};

   std::cout << mf0(1, 2l) << std::endl;
 }

如果您确实希望将指针函数用作模板参数(但是,通过这种方式,每个函数都将确定不同的类型;根据您的需要这可以是好事或坏事),则可以编写myFunc结构先接收类型(相同的指针类型),然后接收该类型的值。

所以

template <typename T, T>
struct myFunc;

template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<R(*)(Args...), Func>
 {
   template <typename ... As>
   R operator() (As && ... args) const
    {
      return Func(std::forward<As>(args)...);
    }
 };

可以声明的

 myFunc<decltype(&foo), foo>  mf0;

如果可以使用C ++ 17,则可以简化使用auto作为模板值的类型;这样就可以避免使用

template <auto>
struct myFunc;

template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<Func>
 {
   template <typename ... As>
   R operator() (As && ... args) const
    {
      return Func(std::forward<As>(args)...);
    }
 };

您可以按照以下步骤创建一个myFunc对象

myFunc<&foo> mf0;

附录:如果可以使用C ++ 17,则可以为第一个示例定义一个演绎指南(指针是成员,而不是模板值参数)

template <typename R, typename ... Args>
myFunc (R(*)(Args...))  -> myFunc<R(*)(Args...)>;

所以,而不是

myFunc<decltype(&foo)>  mf0{&foo};

您可以简单地写

myFunc  mf0{&foo};

关闭主题:我希望您知道自己正在重新发明轮子。根据NathanOliver的建议,该标准提供了std::function