类模板的嵌套模板参数推导不起作用

2024-05-06

In 本次问答 https://stackoverflow.com/a/42221591/819272我编写了一个小包装类,它提供对范围的反向迭代器访问,依赖于类模板的 c++1z 语言功能模板参数推导(p0091r3 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html, p0512r0 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0512r0.pdf)

#include <iostream>
#include <iterator>
#include <vector>

template<class Rng>
class Reverse
{
    Rng const& rng;    
public:    
    Reverse(Rng const& r) noexcept
    : 
        rng(r)
    {}

    auto begin() const noexcept { using std::end; return std::make_reverse_iterator(end(rng)); }
    auto end()   const noexcept { using std::begin; return std::make_reverse_iterator(begin(rng)); }
};

int main()
{
    std::vector<int> my_stack;
    my_stack.push_back(1);
    my_stack.push_back(2);
    my_stack.puhs_back(3);

    // prints 3,2,1
    for (auto const& elem : Reverse(my_stack)) {
        std::cout << elem << ',';    
    }
}

然而,做一个嵌套应用程序Reverse不产生原始迭代顺序

// still prints 3,2,1 instead of 1,2,3
for (auto const& elem : Reverse(Reverse(my_stack))) {
    std::cout << elem << ',';    
}

实例 http://melpon.org/wandbox/permlink/xk0yEumtsG1hp6VT(g++ 7.0 SVN 和 clang 5.0 SVN 的输出相同)

罪魁祸首似乎是类模板的模板参数推导,因为通常的包装函数确实允许正确的嵌套

template<class Rng>
auto MakeReverse(Rng const& rng) { return Reverse<Rng>(rng); }

// prints 1,2,3
for (auto const& elem : MakeReverse(MakeReverse(my_stack))) {
    std::cout << elem << ',';    
}

实例 http://melpon.org/wandbox/permlink/uS9dUBYhWH9Ql4fK(g++ 和 clang 的输出相同)

Question:类模板的嵌套模板参数推导是否应该仅在“一层”深度工作,或者这是 g++ 和 clang 当前实现中的错误?


这可以解释为[超过.匹配.等级.扣除]/p1 http://eel.is/c++draft/over.match.class.deduct#1:

形成一组函数和函数模板,包括:

  • 对于由指定的类模板的每个构造函数模板名称,具有以下属性的函数模板:
  • 模板参数是类模板的模板参数后跟模板参数(包括默认值) 构造函数的模板参数)(如果有)。

  • 函数参数的类型是构造函数的类型。

  • 返回类型是由指定的类模板特化模板名称以及与模板对应的模板参数 从类模板中获取的参数。

我的理解是编译器发明了以下两个函数(两个 - 包括为此类隐式生成的复制构造函数):

template <typename Rng>
Reverse<Rng> foo(const Rng& r);           // #1

template <typename Rng>
Reverse<Rng> foo(const Reverse<Rng>& r);  // #2

然后尝试根据调用选择最佳重载:

foo(Reverse<std::vector<int>>(my_stack));

它解析为#2,因为这个更专业。结论是:

Reverse(Reverse(my_stack))

涉及一个复制构造函数来构造外部Reverse实例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

类模板的嵌套模板参数推导不起作用 的相关文章

随机推荐