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

TemplateRex

此问答中,我编写了一个小的包装器类,该类提供了对范围的反向迭代器访问,它依赖于类模板的c ++ 1z语言功能模板参数推导(p0091r3p0512r0

#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 << ',';    
}

实时示例(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 << ',';    
}

实时示例(与g ++和clang相同的输出)

问题:类模板的嵌套模板参数推论是否应该仅在“一个级别”上起作用,或者这是g ++和clang的当前实现中的错误吗?

巴里

Piotr的答案正确地解释了正在发生的事情-move构造函数比您的构造函数模板更好地匹配。

但是(照常使用TC)有一个比只写工厂更好的解决方法:您可以添加一个明确的推导指南来处理包装:

template <class R>
Reverse(Reverse<R> ) -> Reverse<Reverse<R>>;

关键是要覆盖复制减少候选者,这要归功于[over.match.best]中新添加的首选项:

给定这些定义,如果从推论指南(13.3.1.8)生成了一个可行函数,则该函数F1被定义为比另一个可行函数更好的函数F2F1F2

因此,我们将有四个生成的函数,再次借鉴了Piotr的命名:

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

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

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

template <typename Rng>
Reverse<Reverse<Rng>> foo(Reverse<Rng> r);  // #4 - same-ish as #2/3, but deduction guide

以前,#3由于更专业而被优先考虑。现在,#4首选作为演绎指南。因此,我们仍然可以这样写:

for (auto const& elem : Reverse(Reverse(my_stack))) {
    std::cout << elem << ',';    
}

那行得通。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章