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

mkm*_*afa 8 c++ type-deduction c++17

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);
    }
};
Run Code Online (Sandbox Code Playgroud)

"C++模板,完整指南"第2版​​中,有前面的示例关于带有注入类名的隐式演绎指南的字幕.作者提到,对于注入的类名禁用了类参数推导,因为f的返回类型将X<Iter>归因于隐式推导指南.但我相信模板构造函数的隐式演绎指南更像是下面的那个.

  template <typename T, typename Iter>
  X(Iter a, Iter b) -> X<T>;
Run Code Online (Sandbox Code Playgroud)

我的问题是如何将类模板参数类型,即使在这种情况下,可以推断T,并Iter有两种不同类型和参数类型的唯一依靠Iter.即使T可以某种方式推断出来,T并且Iter是独立的,所以Iter从论证中推断出来并不意味着它的X类型是X<Iter>正确的吗?这是书中的文字有些错误,还是演绎指南看起来与我的想法不同?

Sto*_*ica 5

你是对的.隐式生成的演绎指南确实看起来像你写的那个.模板参数推论永远不会T从中推断出来.这确实不会造成问题.问题在于用户提供的扣除指南.像这样:

template <typename Iter>
X(Iter a, Iter b) -> X<typename Iter::value_type>;
Run Code Online (Sandbox Code Playgroud)

通常添加哪些允许从迭代器中扣除类模板参数.如果注入的类名没有抑制参数推断,那可能会造成严重破坏.作者可能忽略了添加该演绎指南以证明问题的必要性.

以下是问题的说明:

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

这是什么类型的x2?如果我们读取类模板定义,我们希望它与X<float>C++ 14一样,但是如果没有关闭类模板参数演绎并且我们添加了演绎指南,我们就会得到X<int>!

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