实际上,在C++14中可以用非常少的代码完成。
这个想法与@Paul的解决方案非常相似。由于C++11缺少一些东西,那个解决方案有点过度膨胀(而且在std中定义会有味道)。感谢C++14,我们可以使它更加易读。
关键观察是,基于范围的for循环是通过依赖于begin()
和end()
来获取范围的迭代器来工作的。由于ADL,甚至不需要在std命名空间中定义自定义的begin()
和end()
。
这里是一个非常简单的示例解决方案:
template <typename T>
struct reversion_wrapper ;
template <typename T>
auto begin (reversion_wrapper<T> w)
template <typename T>
auto end (reversion_wrapper<T> w)
template <typename T>
reversion_wrapper<T> reverse (T&& iterable) ; }
这真是太棒了,例如:
template <typename T>
void print_iterable (std::ostream& out, const T& iterable)
{
for (auto&& element: iterable)
out << element << ',';
out << '\n';
}
int main (int, char**)
{
using namespace std;
print_iterable(cout, reverse(initializer_list<int> { 1, 2, 3, 4, }));
const list<int> ints_list { 1, 2, 3, 4, };
for (auto&& el: reverse(ints_list))
cout << el << ',';
cout << '\n';
vector<int> ints_vec { 0, 0, 0, 0, };
size_t i = 0;
for (int& el: reverse(ints_vec))
el += i++;
print_iterable(cout, ints_vec);
print_iterable(cout, reverse(ints_vec));
return 0;
}
正如预期的那样打印
4,3,2,1,
4,3,2,1,
3,2,1,0,
0,1,2,3,
注意:GCC-4.9版本中还未实现std::rbegin()
、std::rend()
和std::make_reverse_iterator()
。我根据标准编写这些示例,但它们不能在稳定版本的g++中编译。不过,为这三个函数添加临时存根非常容易。下面是一个示例实现,虽然不完整,但对于大多数情况已经足够:
template <typename I>
reverse_iterator<I> make_reverse_iterator (I i)
{
return std::reverse_iterator<I> { i };
}
template <typename T>
auto rbegin (T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
template <typename T>
auto rbegin (const T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (const T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
begin
到end
迭代或处理流迭代器等情况时更好且更简洁。虽然范围算法很棒,但它们实际上只是迭代器算法的语法糖(除了可能有惰性评估的可能性)。 - Nicol Bolasconst
版本等),但它已经能够正常工作。以下是示例代码:vector<int> v {1, 2, 3}; reverse_adapter<decltype(v)> ra; for (auto& i : ra) cout << i;
输出结果为321
。 - Seth Carnegietemplate<typename T> reverse_adapter<T> reverse_adapt_container(T &c) {return reverse_adapter<T>(c);}
这样你就可以使用for(auto &i: reverse_adapt_container(v)) cout << i;
来迭代了。 - Nicol Bolasparallel_for
就是这种情况下的更强烈的“我不关心顺序”的条件。当然,它也可以具有基于范围的语法糖 :-) - Steve Jessop