【问题标题】:Template argument deduction trick for constructor with parameters depending on integer template具有取决于整数模板的参数的构造函数的模板参数推导技巧
【发布时间】:2017-06-18 09:50:43
【问题描述】:

我在https://stackoverflow.com/a/36132696/3206356 中找到了一个代码,我试了一下。它有效,但我不完全理解那里发生了什么。

我从下面的链接中复制了代码:

template <size_t N, class = std::make_index_sequence<N>>
class Vector;

template <size_t N, size_t... Is>
class Vector<N, std::index_sequence<Is...>> 
{
private:
    std::array<double, N> vals;

    template <size_t >
    using double_ = double;
public:
    Vector(double_<Is>... vals)
    {
        ...
    }
};

例如,我们尝试下一个方式使用它:

Vector<3> a(1.0, 2.0, 3.0);

类型推导在这里如何运作?

附言 据我了解,当编译器看到该行时,首先,它会尝试推断类型以进行专门化。它将N 推断为 3,Is 推断为空序列,然后在找不到合适的构造函数时失败。通用模板没有定义,所以编译器在这里也必须失败。但接下来会发生什么?

【问题讨论】:

  • 不,它将 N 推导出为 3,然后将第二个参数推导出为 std::make_index_sequence&lt;3&gt;,因为这是默认模板参数所说的。 Is... 永远不能是空序列(除非 N0)。
  • 但是来自通用模板的N 和来自专业化的N 是不同的。当我写到N 被推断为3 时,我的意思是专业化。据我了解,当我们推断专业化类型时,我们对std::make_index_sequence&lt;N&gt; 一无所知。我错了吗?
  • 它是这样工作的。编译器看到Vector&lt;3&gt;。它进入主模板,推导出它可以的参数,并填充具有默认值的参数。这会将Vector&lt;3&gt; 变成Vector&lt;3, std::make_index_sequence&lt;3&gt;&gt;然后为此实例化找到合适的特化并再次推导参数。
  • 我现在明白了!谢谢! =)

标签: c++ templates


【解决方案1】:

这部分声明(不是定义)模板类 Vector 的默认特化。第二个模板参数默认为索引序列 0...N-1

template <size_t N, class = std::make_index_sequence<N>>
class Vector;

默认参数很重要,因为它用于呈现简单的界面并隐藏下一个专业化的复杂性...

这种特化是上述默认声明的结果。索引序列的目的是携带Is的可变参数序列(即0 ... N-1)。

template <size_t N, size_t... Is>
class Vector<N, std::index_sequence<Is...>> 
{

定义足够的存储空间

private:
    std::array<double, N> vals;

提供一种将序列 Is 从 size_t 转换为类型(在本例中为 double)的方法

    template <size_t >
    using double_ = double;

public:

将构造函数定义为采用double_&lt;0&gt;double_&lt;1&gt; ... double_&lt;N-1&gt;。但是任何Ndouble&lt;N&gt;double 的typedef。所以这条线正在做的是提供一个构造函数,它为每个Is 使用一个double。即构建数组所需的双精度数。其实很聪明。

    Vector(double_<Is>... vals)
    {
        ...
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多