#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;
}
