【问题标题】:Fixed Length Variadic Parameter Packs in C++11C++11 中的固定长度可变参数包
【发布时间】:2014-08-30 23:08:28
【问题描述】:

我正在尝试使用 C++11 实现一个广义的 n 维向量类。理想情况下,我想提供向量的类型“T”和维数“n”,并让构造函数接受适当数量的参数。

不幸的是,我一直无法找到一种方法来允许参数包的模板指定的固定长度。

我正在寻找类似的东西

template<typename T, size_t n>
class Vector {
public:
    Vector(T... values /* values is exactly n parameters long */);

    ...
};

可以这样做吗?

【问题讨论】:

  • 这里有std::array

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


【解决方案1】:

好吧,你可以使用 std::enable_if:

template <typename... Args,
    typename = typename std::enable_if<
        sizeof...(Args) == n
    >::type>
explicit Vector(Args&&... values) : _data{ std::forward<Args>(values)... } {}

它将影响可以接受除 n 以外的 Args 大小的构造函数。

【讨论】:

  • 有趣。你能解释一下构造函数初始化列表中发生了什么吗?我对 C++11 标准相当陌生,很难弄清楚它是如何工作的。谢谢!
  • 只是简单的移动构造函数。我假设 __data 是这样定义的: T __data[n];初始化列表只是将值从构造函数参数移动到 __data 数组。您应该阅读有关 std::move 的内容,它非常棒。
【解决方案2】:

你也可以使用这个技巧:

template <typename T, std::size_t n, typename = std::make_index_sequence<n>>
class Vector;

template <typename T, std::size_t n, std::size_t... Ignore>
class Vector<T, n, std::index_sequence<Ignore...>>
{
    template <size_t > using ith_T = T;
public:
    Vector(ith_T<Ignore>... values)
    {
    }
};

这将确保Vector 采用n 类型的T 参数,无需额外的模板。您还可以在命名空间中隐藏Ignore... ugliness:

namespace details {
    template <typename T, std::size_t n, typename = std::make_index_sequence<n>>
    class Vector;

    ...
}

template <typename T, std::size_t n>
using Vector = details::Vector<T, n>;

【讨论】:

  • 你能解释一下这里发生了什么吗?
  • @Kikohs 创建了正确长度的包(通过默认参数和make_index_sequence)。这个包是由专业化匹配的模式。这个包然后以每个实例成为T 类型的方式解包。我们得到一个 ctor,它要求恰好是 nT 实例。我不喜欢 Barry 使用 details::make(为什么要使用 decltypetemplate&lt;std::size_t I&gt; using ith_T=T; Vector(ith_T&lt;Ignore&gt;...)),如果最终用户通过了有缺陷的第三个参数,事情就会变得很糟糕,但除此之外,它还有效。跨度>
  • @Yakk 好得多,是的。
猜你喜欢
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-05
相关资源
最近更新 更多