#include #include using namespace std; typedef tuple Tuple; int const Num = tuple_size::value; template ostream& operator<<(ostream& os, tuple const& t) { return os << "{" << get<0>(t) << "," << get<1>(t) << "}"; } template ostream& operator<<(ostream& os, tuple const& t) { return os << "{" << get<0>(t) << "," << get<1>(t) << "," << get<2>(t) << "}"; } // odo short for odometer. template struct odo_right_to_left { template static void apply(tuple& i, tuple const& b, tuple const& e) { // Only increment when you're non-empty. if(get(i) == get(e)) { // TODO: If the range in N (b, e] is guaranteed to be non-empty, then we // can omit this check. odo_right_to_left::apply(i, b, e); } else { // Incrementing the current element. If the increment pushes this past // the end, then increment the previous (next lower) iterator. ++get(i); if(get(i) == get(e)) { get(i) = get(b); odo_right_to_left::apply(i, b, e); } } } }; template<> struct odo_right_to_left<0> { template static void apply(tuple& i, tuple const& b, tuple const& e) { if(get<0>(i) == get<0>(e)) { // If the last position is invalid, then we should probably need to // invalidate the entire odometer. i = e; } else { // As before, but if we reach the end in the outermost iterator, reset the // entire tuple to be equal to end. ++get<0>(i); if(get<0>(i) == get<0>(e)) { i = e; } } } }; template void incr_right_to_left(tuple& i, tuple const& b, tuple const& e) { odo_right_to_left::apply(i, b, e); } // odo short for odometer. template struct odo_left_to_right { template static void apply(tuple& i, tuple const& b, tuple const& e) { // Only increment when you're non-empty. if(get(i) == get(e)) { // TODO: If the range in N (b, e] is guaranteed to be non-empty, then we // can omit this check. odo_left_to_right::apply(i, b, e); } else { // Incrementing the current element. If the increment pushes this past // the end, then increment the previous (next lower) iterator. ++get(i); if(get(i) == get(e)) { get(i) = get(b); odo_left_to_right::apply(i, b, e); } } } }; template struct odo_left_to_right { template static void apply(tuple& i, tuple const& b, tuple const& e) { if(get(i) == get(e)) { // Invalidate the entire counter. i = e; } else { ++get(i); if(get(i) == get(e)) { get(i) = get(b); i = e; } } } }; template void incr_left_to_right(tuple& i, tuple const& b, tuple const& e) { odo_left_to_right::apply(i, b, e); } int main() { { Tuple i, b, e(2, 3, 4); int n = 0; for( ; i != e; incr_right_to_left(i, b, e)) { cout << n++ << " " << i << "\n"; } } cout << "---------------\n"; { Tuple i, b, e(2, 5, 3); int n = 0; for( ; i != e; incr_left_to_right(i, b, e)) { cout << n++ << " " << i << "\n"; } } return 0; }