В этот Q & A Я написал небольшой класс-оболочку, который предоставляет обратный итератор доступ к диапазону, полагаясь на С++ 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 << ',';
}
Пример Live (тот же вывод для 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 << ',';
}
Пример Live (тот же вывод для g++ и clang)
Вопрос: вывод вложенного аргумента шаблона для шаблонов классов, которые должны работать только на "одном уровне", или это ошибка в текущих реализациях как g++, так и clang?