#include <iostream>
#include <sstream>
#include <list>
#include <cassert>
template <typename T>
class sequence
{
private:
std::list<T> _l;
typename std::list<T>::iterator _i;
public:
using value_type = T;
using size_type = typename std::list<T>::size_type;
size_type size() const {
return _l.size();
}
T current() const {
assert(is_current_valid());
return *_i;
}
size_type current_index() const {
return _i - _l.begin();
}
void increase_current() {
if (is_current_valid()) {
++_i;
}
}
void decrease_current() {
if (_i != _l.begin()) {
--_i;
}
}
void reset_current() {
_i = _l.begin();
}
bool is_current_valid() const {
// "is_item"
return _i != _l.end();
}
void remove_current() {
assert(is_current_valid());
// _i takes the next current element, eventually end()
_i = _l.erase(_i);
}
void insert_before(const value_type &entry) {
// _i is always the newly inserted element
_i = _l.insert(_i, entry);
}
void insert_after(const value_type &entry) {
// _i is always the newly inserted element
assert(is_current_valid());
_i = _l.insert(++_i, entry);
}
friend std::ostream &operator<<(std::ostream &os, sequence const &s) {
for (auto it = s._l.begin(); it != s._l.end(); ++it) {
if (it != s._l.begin()) {
os << " " << *it;
} else {
os << *it;
}
}
return os;
}
sequence() : _l(), _i(_l.end()) {}
};
int main() {
sequence<std::size_t> numbers;
numbers.insert_before(21); // insert 21, then points to 21
numbers.insert_after(33); // 33 after 21, then points to 33
numbers.insert_before(22); // 22 before 21, then points to 22
std::cout << numbers << std::endl;
// Programmatically check if the result is the requested one
const std::string expected = "21 22 33";
std::stringstream output;
output << numbers;
if (output.str() != expected) {
std::cerr << "Error!" << std::endl;
return 1;
}
return 0;
}