3 回答

TA貢獻1818條經驗 獲得超11個贊
實際上,Boost確實具有這樣的適配器:boost::adaptors::reverse。
#include <list>
#include <iostream>
#include <boost/range/adaptor/reversed.hpp>
int main()
{
std::list<int> x { 2, 3, 5, 7, 11, 13, 17, 19 };
for (auto i : boost::adaptors::reverse(x))
std::cout << i << '\n';
for (auto i : x)
std::cout << i << '\n';
}

TA貢獻1789條經驗 獲得超8個贊
實際上,在C ++ 14中,只需幾行代碼即可完成。
這在思想上與@Paul的解決方案非常相似。由于C ++ 11中缺少某些內容,因此該解決方案有點不必要地過大(加上在std氣味中定義)。感謝C ++ 14,我們可以使它更具可讀性。
關鍵的觀察結果是,基于范圍的for循環通過依賴begin()和end()來獲取范圍的迭代器而工作。由于ADL,一個甚至不需要定義自己的自定義begin(),并end()在的std ::命名空間。
這是一個非常簡單的示例解決方案:
// -------------------------------------------------------------------
// --- Reversed iterable
template <typename T>
struct reversion_wrapper { T& iterable; };
template <typename T>
auto begin (reversion_wrapper<T> w) { return std::rbegin(w.iterable); }
template <typename T>
auto end (reversion_wrapper<T> w) { return std::rend(w.iterable); }
template <typename T>
reversion_wrapper<T> reverse (T&& iterable) { return { 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;
// on prvalues
print_iterable(cout, reverse(initializer_list<int> { 1, 2, 3, 4, }));
// on const lvalue references
const list<int> ints_list { 1, 2, 3, 4, };
for (auto&& el: reverse(ints_list))
cout << el << ',';
cout << '\n';
// on mutable lvalue references
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,
注意 std::rbegin(),std::rend()和std::make_reverse_iterator()尚未在GCC-4.9中實現。我根據標準編寫了這些示例,但是它們無法在穩定的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());
}
// const container variants
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());
}

TA貢獻1828條經驗 獲得超3個贊
這應該可以在C ++ 11中正常工作而無需增強:
namespace std {
template<class T>
T begin(std::pair<T, T> p)
{
return p.first;
}
template<class T>
T end(std::pair<T, T> p)
{
return p.second;
}
}
template<class Iterator>
std::reverse_iterator<Iterator> make_reverse_iterator(Iterator it)
{
return std::reverse_iterator<Iterator>(it);
}
template<class Range>
std::pair<std::reverse_iterator<decltype(begin(std::declval<Range>()))>, std::reverse_iterator<decltype(begin(std::declval<Range>()))>> make_reverse_range(Range&& r)
{
return std::make_pair(make_reverse_iterator(begin(r)), make_reverse_iterator(end(r)));
}
for(auto x: make_reverse_range(r))
{
...
}
- 3 回答
- 0 關注
- 1939 瀏覽
添加回答
舉報