#pragma once #include #include #include namespace gp { struct index_to_1 { size_t value; index_to_1(size_t v) : value{v + 1} {} void left() { value <<= 1; } void right() { value = (value << 1) + 1; } void up() { value >>= 1; } bool is_right() const { return value & 1; } bool is_left() const { return !(value & 1); } bool is_root() const { return value == 1; } operator size_t() { return value - 1; } }; template struct flat_tree_iterator { reflect& tree; size_t index; bool has_right(index_to_1 v) const { v.right(); return (v < tree.data().size()) && (tree.data()[v].has_value()); } bool has_left(index_to_1 v) const { v.left(); return (v < tree.data().size()) && (tree.data()[v].has_value()); } flat_tree_iterator& operator++() { index = next(); return *this; } flat_tree_iterator operator++(int) { auto cpy = *this; index = next(); return cpy; } size_t next() const { index_to_1 it{index}; enum class cases { right_climber, left_climber, descender, starter }; const cases current_case = [&](){ if(index == (size_t)-1) { return cases::starter; } else if(has_right(it)) { return cases::descender; } else if(it.is_left()) { return cases::left_climber; } else { return cases::right_climber; } }(); switch(current_case) { case cases::starter: { it = index_to_1{0}; while(has_left(it)) { it.left(); } } break; case cases::descender: { it.right(); while(has_left(it)) { it.left(); } } break; case cases::left_climber: { it.up(); } break; case cases::right_climber: { while(it.is_right()) { it.up(); } if(it.is_root()) { it.value = -1; } } break; } return it; } bool operator!=(flat_tree_iterator rhs) { return index != rhs.index; } T& operator*() { return tree.data_[index].value(); } }; }