【问题标题】:Obtain all-but-last parameter of variadic template获取Variadic模板的全部除最后参数
【发布时间】:2015-07-06 21:24:32
【问题描述】:

我有一个这样声明的 ctor:

template<typename... Coords>
MyClass<T>(vector<T> values, Coords... coords) { /* code */ }

我希望它看起来像这样:

template<typename... Coords>
MyClass<T>(Coords... coords, vector<T> values) { /* code */ }

但标准要求可变参数是最后一个。如果我写类似

template<typename... Args>
MyClass<T>(Args... coordsThenValues) { /* code */ }

我如何将coordsThenValues 拆分为最后一个参数包Coords... coords 和最后一个参数vector&lt;T&gt; values

【问题讨论】:

  • 你喜欢元组吗?你觉得dem tuples怎么样?

标签: c++ c++11 variadic-templates


【解决方案1】:

你喜欢元组吗?

作为元组,你如何看待 forward?

struct foo {
  template<class...Ts>
  foo(Ts&&...ts):
    foo(
      magic<0>{}, // sent it to the right ctor
      std::index_sequence< sizeof...(ts)-1 >{}, // the last shall be first
      std::make_index_sequence<sizeof...(ts)-1>{}, // the first shall be last
      std::forward_as_tuple(std::forward<Ts>(ts)...) // bundled args
    )
  {}
private:
  template<size_t>
  struct magic {};
  template<size_t...I0s, size_t...I1s, class...Ts>
  foo(
    magic<0>, // tag
    std::index_sequence<I0s...>, // first args
    std::index_sequence<I1s...>, // last args
    std::tuple<Ts...> args // all args
  ):
    foo(
      magic<1>{}, // dispatch to another tagged ctor
      std::get<I0s>(std::move(args))..., // get first args
      std::get<I1s>(std::move(args))... // and last args
    )
  {}
  // this ctor gets the args in an easier to understand order:
  template<class...Coords>
  foo(magic<1>, std::vector<T> values, Coords...coords) {
  }
};

这里公共 ctor 将参数打包成一个引用元组(可能是 l,也可能是 r)。它还获得了两组索引。

然后它将它发送到magic&lt;0&gt;ctor,它会随机排列参数,以便最后一个是第一个(假设索引是正确的)。

magic&lt;1&gt; ctor 首先获取向量,然后是坐标。

基本上我改变了争论,所以最后一个成为第一个。

magic 的存在只是为了让我不必过多考虑重载解决方案,并使我转发给明确的 ctor。如果没有它,它可能会工作,但我喜欢在使用 ctor 转发做一些疯狂的事情时进行标记。

【讨论】:

  • 应该是std::forward_as_tuple(std::forward&lt;Ts&gt;(ts)...),除此之外这是完美的。
  • 我稍微修改了你的代码。主要问题是:foo(Ts&amp;&amp;...ts) 捕获一切。如果 magic&lt;0&gt; ctor 尝试使用无效参数传递给 magic&lt;1&gt; ctor,则传递将失败,它实际上会调用 foo(Ts&amp;&amp;...ts) 导致无限编译器循环。所以我写的不是template&lt;class...Ts&gt;,而是template&lt;class...Ts, typename = std::enable_if&lt;(sizeof...(Ts) &gt; 1 &amp;&amp; !(is_magic&lt;NthTypeOf&lt;0, Ts...&gt;&gt;::value))&gt;::type&gt;。 (我把magic移到类定义之外,写了一个简单的is_magicNthTypeOf)。
  • @arcinde @arcinde magic 的要点之一是没有其他人(除了班级)有权创建它。哪个颠覆了。
  • template&lt;size_t n&gt; static std::true_type is_magic_f( magic&lt;n&gt; ) { return {}; } template&lt;class T&gt; static std::false_type is_magic_f( T ) { return {}; } template&lt;class T&gt; using is_magic = decltype( is_magic_f( std::declval&lt;T&gt;() ) ); ;)
  • @igor 或者只是删除那里的&amp;&amp;
猜你喜欢
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 2013-10-16
  • 2018-06-18
  • 2018-05-07
  • 2016-06-30
  • 2013-08-27
  • 1970-01-01
相关资源
最近更新 更多