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

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

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

我的问题是我遇到了“catch 22”,其中'Args...'必须是最后一个模板参数,但同时,在函数指针模板参数之后无法定义。

知道这是否真的可以解决?

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

    void operator ()(Args... args) const
    {
      (*Function)(std::forward<Args...>(args...));
    }
  };
c++ templates variadic-templates c++03 template-deduction
1个回答
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)...);
    }

其中funR(*)(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

© www.soinside.com 2019 - 2024. All rights reserved.