作为模板参数的函数

functions as template arguments

本文关键字:函数 参数      更新时间:2023-10-16

我有一个TaskWrapper:

template <typename T, T (*F)(T)>
struct TaskWrapper {
  static inline T run(T clock) {
    return F(clock);
  }
};
要使用它,我必须指定T模板参数:
uint16_t task1(uint16_t clock) { return clock + 1; }
typedef tasks::TaskWrapper<uint16_t, task1> Task;

我想简单地写:

typedef tasks::TaskWrapper<task1> Task;

,让编译器计算出返回值和参数类型是uint16_t。

指出:

TaskWrapper显然被简化了,实际上还有一些其他的参数,这些参数是在类型定义期间传递的。

包装函数只能是:

uint8_t task(uint8_t clock);
uint16_t task(uint16_t clock); // or
uint32_t task(uint32_t clock);

TaskWrapper作为模板参数传递给另一个类,该类将在某个时候调用Task::run(…);

c++ 11就可以了

仅从c++ 17的模板特点:

template <auto F>
struct TaskWrapper {
  template <typename T>
  static inline auto run(T clock) {
    return F(clock);
  }
};
uint16_t task1(uint16_t clock) { return clock + 1; }
typedef TaskWrapper<&task1> Task; // ok

您可以将模板参数移动到调用的位置,但这会使它与传递给演绎的参数相对应,例如:

template <typename F, F functor>
struct TaskWrapper {
  template<typename T>
  static inline T run(T clock) {
    return functor(clock);
  }
};
uint16_t task1(uint16_t clock) { return clock + 1; }
typedef TaskWrapper<decltype(task1), task1> Task;
int main(int argc, const char * argv[])
{
  Task task;
  Task::run(10);
  return 0;
}

这样它将生成一个static inline int run(int clock),它与初始函数的参数类型不同,但对于您的目的来说已经足够了。

使用类型而不是值作为参数时,模板很容易。你能把函数转换成函子吗?如果是,那么可能的解决方案如下:

template<class F>
struct TaskWrapper {
  using T = decltype(F::operator());
  static inline T run(T clock) {
    return F(clock);
  }
};
struct task1_t {
  uint16_t operator()(uint16_t clock) {
    return clock + 1;
  }
};
using Task = TaskWrapper<task1_t>;

我不认为这是可能的,你到底问什么:如果你想传递函数作为模板,不表达类型,你必须知道类型之前;但是函数的类型是你想要推断的。

如果接受传递函数的类型,如下所示

template <typename>
struct taskWrapper;
template <typename T>
struct taskWrapper<std::function<T(T)>>
 {
   static inline T run (std::function<T(T)> const & F, T clock)
    { return F(clock); };
 };

你可以定义定义你的typedef s

typedef taskWrapper<std::function<decltype(task8)>>  tsk8;
typedef taskWrapper<std::function<decltype(task16)>> tsk16;
typedef taskWrapper<std::function<decltype(task32)>> tsk32;

,但可以看到taskWrapper<std::function<decltype(task8)>>只知道task8()类型,不知道task8()函数本身;所以你必须把函数传递给run()

下面是一个工作示例:

#include <iostream>
#include <functional>
template <typename>
struct taskWrapper;
template <typename T>
struct taskWrapper<std::function<T(T)>>
 {
   static inline T run (std::function<T(T)> const & F, T clock)
    { return F(clock); };
 };
uint8_t task8 (uint8_t clock)
 { return ++clock; }
uint16_t task16 (uint16_t clock)
 { return ++clock; }
uint32_t task32 (uint32_t clock)
 { return ++clock; }
typedef taskWrapper<std::function<decltype(task8)>>  tsk8;
typedef taskWrapper<std::function<decltype(task16)>> tsk16;
typedef taskWrapper<std::function<decltype(task32)>> tsk32;
int main ()
 {
   tsk8   t8;
   tsk16  t16;
   tsk32  t32;
   std::cout << t8.run(task8,   uint8_t(64)) << std::endl;  // print A
   std::cout << t16.run(task16, uint16_t(65)) << std::endl; // print 66
   std::cout << t32.run(task32, uint32_t(66)) << std::endl; // print 67
 }