【问题标题】:Is there any elegant way? (type parameter pack)有什么优雅的方法吗? (类型参数包)
【发布时间】:2019-03-12 01:23:16
【问题描述】:

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

我已经尝试过的是下面,但它只调用了基函数(用AModule类调用了基函数,没有用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 没有在main 之前声明) - 即使您修复了这个问题并添加了缺少的分号,我也不希望您描述的行为(打电话给init&lt;A&gt;,但不是init&lt;B&gt;),我希望对init&lt;B&gt;有一个模棱两可的电话。

标签: c++ templates recursion c++17 variadic-templates


【解决方案1】:

在您的示例代码中,您使用的是模板折叠,这是一种新的 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&lt;Tail...&gt;();,直到Tail... 不为空称为Head/Tail... 递归版本。

Tail... 为空时,init&lt;Tail...&gt;()init&lt;&gt;(),因此Head/Tail... 版本不再匹配(没有Head)但匹配int = 0 版本;所以init&lt;&gt;() 变成init&lt;0&gt;() 并且ground-do-nothing 情况停止递归。

【讨论】:

    【解决方案2】:

    在您的代码中(一旦语法错误得到修复),两个 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

    【讨论】:

      猜你喜欢
      • 2013-10-14
      • 2012-04-09
      • 2012-04-15
      • 1970-01-01
      • 1970-01-01
      • 2015-03-27
      • 2019-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多