有什么优雅的方法吗? (类型参数包)

Is there any elegant way? (type parameter pack)

我想制作一个接受类型并通过循环或递归再次调用自身的函数。

下面是我已经尝试过的,但它只调用了基本函数(Called base function with AModule class and didn't call the function with BModule.

class AModule {
};
class BModule {
};

auto main() -> int {
  init<AModule, BModule>()
  return 0;
}

template<typename Module>
void init() {
  // BASE FUNCTION
  // Do something
}

template<typename... Modules>
void init() {
  (init<Modules>(), ...)
}

在您的代码中(修复语法错误后),两个 init() 调用都对 1 个模板参数有效,因此该调用不明确。通过使 multi-init 调用至少需要 2 个参数,消除了歧义。

// bogus type that just prints an error message including the type it is parameterized with
template<typename T>
struct printer;

template<typename Module>
void init() {
 printer<Module>{}; // this is an error just to show you that it's getting called with both types
}

// only call this if it's called with 2 or more types, otherwise just use the other init()
template<typename T1, typename T2, typename... Modules>
void init() {
    init<T1>();
    init<T2>();
  (init<Modules>(), ...);
}

class AModule {
};
class BModule {
};

auto main() -> int {
  init<AModule, BModule>();
  return 0;
}

直播:https://godbolt.org/z/D-eh2G

在您示例的代码中,您使用了模板折叠,这是一种新的 C++17 功能,可让您避免递归。

但是,为了避免名称冲突,我建议以不同的方式调用基本版本;说 do_something()

template<typename Module>
void do_something() {
  // BASE FUNCTION
  // Do something
}

template<typename... Modules>
void init() {
  (do_something<Modules>(), ...);
}

如果你真的想使用递归的方式,你可以这样做

template <int = 0>
void init ()
 {
  // stop recursion; do nothing
 }

template <typename Head, typename ... Tail>
void init () 
 {
   // do something with Head

   // recursively call init()
   init<Tail...>();
 }

诀窍是调用 init<Tail...>();,直到 Tail... 不为空称为 Head/Tail... 递归版本。

Tail... 为空时,init<Tail...>()init<>(),因此 Head/Tail... 版本不再匹配(没有Head) 但匹配 int = 0 版本;所以 init<>() 变成 init<0>() 并且地面什么都不做的情况停止递归。