실제로 C ++ 14에서는 매우 적은 코드 줄로 수행 할 수 있습니다.
이것은 @Paul의 솔루션과 매우 유사합니다. C ++ 11에서 누락 된 것이 있기 때문에이 솔루션은 불필요하게 부풀어 오른 것입니다 (표준 냄새로 정의). C ++ 14 덕분에 훨씬 더 읽기 쉽게 만들 수 있습니다.
주요 관찰에 의존하여 그 범위 기반에 대한-루프 작품 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());
}