Created
September 2, 2012 15:06
-
-
Save klmr/3600202 to your computer and use it in GitHub Desktop.
Range-based for in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef UTIL_LANG_RANGE_HPP | |
#define UTIL_LANG_RANGE_HPP | |
#include <iterator> | |
namespace util { namespace lang { | |
namespace detail { | |
template <typename T> | |
struct range_iter_base : std::iterator<std::input_iterator_tag, T> { | |
range_iter_base(T current) : current(current) { } | |
T operator *() const { return current; } | |
T const* operator ->() const { return ¤t; } | |
range_iter_base& operator ++() { | |
++current; | |
return *this; | |
} | |
range_iter_base operator ++(int) { | |
auto copy = *this; | |
++*this; | |
return copy; | |
} | |
bool operator ==(range_iter_base const& other) const { | |
return current == other.current; | |
} | |
bool operator !=(range_iter_base const& other) const { | |
return not (*this == other); | |
} | |
protected: | |
T current; | |
}; | |
} // namespace detail | |
template <typename T> | |
struct range_proxy { | |
struct iter : detail::range_iter_base<T> { | |
iter(T current) : detail::range_iter_base<T>(current) { } | |
}; | |
struct step_range_proxy { | |
struct iter : detail::range_iter_base<T> { | |
iter(T current, T step) | |
: detail::range_iter_base<T>(current), step(step) { } | |
using detail::range_iter_base<T>::current; | |
iter& operator ++() { | |
current += step; | |
return *this; | |
} | |
iter operator ++(int) { | |
auto copy = *this; | |
++*this; | |
return copy; | |
} | |
private: | |
T step; | |
}; | |
step_range_proxy(T begin, T end, T step) | |
: begin_(begin, step), end_(end, step) { } | |
iter begin() const { return begin_; } | |
iter end() const { return end_; } | |
private: | |
iter begin_; | |
iter end_; | |
}; | |
range_proxy(T begin, T end) : begin_(begin), end_(end) { } | |
step_range_proxy step(T step) { | |
return step_range_proxy(*begin_, *end_, step); | |
} | |
iter begin() const { return begin_; } | |
iter end() const { return end_; } | |
private: | |
iter begin_; | |
iter end_; | |
}; | |
template <typename T> | |
struct infinite_range_proxy { | |
struct iter : detail::range_iter_base<T> { | |
iter(T current = T()) : detail::range_iter_base<T>(current) { } | |
bool operator ==(iter const&) const { return false; } | |
bool operator !=(iter const&) const { return true; } | |
}; | |
struct step_range_proxy { | |
struct iter : detail::range_iter_base<T> { | |
iter(T current = T(), T step = T()) | |
: detail::range_iter_base<T>(current), step(step) { } | |
using detail::range_iter_base<T>::current; | |
iter& operator ++() { | |
current += step; | |
return *this; | |
} | |
iter operator ++(int) { | |
auto copy = *this; | |
++*this; | |
return copy; | |
} | |
bool operator ==(iter const&) const { return false; } | |
bool operator !=(iter const&) const { return true; } | |
private: | |
T step; | |
}; | |
step_range_proxy(T begin, T step) : begin_(begin, step) { } | |
iter begin() const { return begin_; } | |
iter end() const { return iter(); } | |
private: | |
iter begin_; | |
}; | |
infinite_range_proxy(T begin) : begin_(begin) { } | |
step_range_proxy step(T step) { | |
return step_range_proxy(*begin_, step); | |
} | |
iter begin() const { return begin_; } | |
iter end() const { return iter(); } | |
private: | |
iter begin_; | |
}; | |
template <typename T> | |
range_proxy<T> range(T begin, T end) { | |
return range_proxy<T>(begin, end); | |
} | |
template <typename T> | |
infinite_range_proxy<T> range(T begin) { | |
return infinite_range_proxy<T>(begin); | |
} | |
} } // namespace util::lang | |
#endif // ndef UTIL_LANG_RANGE_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "range.hpp" | |
using std::cout; | |
using util::lang::range; | |
int main() { | |
for (auto const i : range(1, 5)) | |
cout << i << "\n"; | |
for (auto const u : range(0u)) | |
if (u == 3u) break; | |
else cout << u << "\n"; | |
for (auto const c : range('a', 'd')) | |
cout << c << "\n"; | |
for (auto const u : range(20u, 30u).step(2u)) | |
cout << u << "\n"; | |
for (auto const i : range(100).step(-3)) | |
if (i < 90) break; | |
else cout << i << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment