演绎指南和注入的班级名称

时间:2018-07-03 07:33:19

标签: c++ c++17 type-deduction

template <typename T>
struct X
{
    template <typename Iter>
    X(Iter a, Iter b) {}

    template <typename Iter>
    auto f(Iter a, Iter b)
    {
        return X(a, b);
    }
};

“ C ++模板,完整指南” 第二版中,有一个先前的示例,该示例涉及带有注入类名的隐式演绎指南的字幕。作者提到对于注入的类名禁用类参数推论,因为由于隐式推论指南,f返回的类型为X<Iter>。但是我相信模板构造函数的隐式推导指南看起来像下面的指南。

  template <typename T, typename Iter>
  X(Iter a, Iter b) -> X<T>;

我的问题是,在这种情况下,TIter是两个截然不同的类型,而参数类型仅依赖于Iter,如何推导类模板参数类型。同样,即使可以以某种方式推导T,TIter是独立的,所以从参数推论Iter并不意味着X的类型为X<Iter>吗?书中的文字是否有此错误,还是推导指南看起来与我的想法有所不同?

1 个答案:

答案 0 :(得分:5)

您是正确的。隐式生成的推导指南确实看起来就像您编写的那样。模板参数推论永远无法从中推论T。确实不会造成任何问题。问题出在用户提供的扣除指南上。像这样:

template <typename Iter>
X(Iter a, Iter b) -> X<typename Iter::value_type>;

Which are often added to allow class template argument deduction from iterators。如果注入的类名不抑制自变量推导,那可能会造成严重破坏。作者可能忽略了添加该演绎指南以演示该问题的需要。

以下是问题的说明:

auto v = std::vector<int>{1, 2};
auto x1 = X<float>(begin(v), end(v));
auto x2 = x1.f(begin(v), begin(v));

x2是什么类型?如果我们阅读了类模板定义,我们期望它是X<float>,就像在C ++ 14中一样,但是如果没有关闭类模板参数推导并且添加推论指南,我们将得到X<int>

想象一下现有的代码库,其中的类型在移至C ++ 17之后突然转变。那将是非常糟糕的。