在这个问答中,我编写了一个小封装类,为范围提供反向迭代器访问,并依赖于C++1z语言特性模板参数推导的类模板(p0091r3, p0512r0)。
#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当前实现中的错误?
my_stack
是一个命名变量,并且引用被存储在Reverse
对象内部,所以这里有什么悬空呢? - TemplateRexReverse(my_stack)
不是一个命名变量,而你在Reverse(Reverse(my_stack))
内部存储了对它的引用。 - cpplearnerReverse
的构造函数是一个拷贝构造函数,因此使用相同的模板参数。 - Albjenow