#include <algorithm>
#include <iostream>
#include <iterator>

class MyIterator : public std::iterator<std::random_access_iterator_tag, double>
{
public:
	MyIterator() : container(nullptr), i(0), j(0) {}

	MyIterator(const std::vector<std::vector<double>>& container,
			   std::size_t i,
			   std::size_t j) : container(&container), i(i), j(j)
	{
		// Skip empty container
		if (i < container.size() && container[i].empty())
		{
			j = 0;
			++(*this);
		}
	}
	MyIterator(const MyIterator& rhs) = default;
	MyIterator& operator = (const MyIterator& rhs) = default;

	MyIterator& operator ++() {
		if (++j >= (*container)[i].size()) {
		    do {++i;} while (i < (*container).size() && (*container)[i].empty());
		    j = 0;
		}
		return *this;
	}
	MyIterator operator ++(int) { auto it = *this; ++(*this); return it; }
	
	MyIterator& operator --() {
		if (j-- == 0) {
			do  { --i; } while (i != 0 && (*container)[i].empty());
			j = (*container)[i].size();
		}
		return *this;
	}
	MyIterator operator --(int) { auto it = *this; --(*this); return it; }
	
	double operator *() const { return (*container)[i][j]; }
	
	
	bool operator == (const MyIterator& rhs) const {
		return container == rhs.container && i == rhs.i && j == rhs.j;
	}
	bool operator != (const MyIterator& rhs) const { return !(*this == rhs); }
	
private:
	const std::vector<std::vector<double>>* container;
	std::size_t i;
	std::size_t j;
};

MyIterator MyIteratorBegin(const std::vector<std::vector<double>>& container)
{
	return MyIterator(container, 0, 0);
}

MyIterator MyIteratorEnd(const std::vector<std::vector<double>>& container)
{
	return MyIterator(container, container.size(), 0);
}

int main() {
	std::vector<std::vector<double>> values = {{5,0,8}, {}, {3,1,9}};
	
	auto b = MyIteratorBegin(values);
	auto e = MyIteratorEnd(values);
	auto p = std::minmax_element(b, e);
	
	if (p.first != e) {
		std::cout << "min is " << *p.first << " and max is " << *p.second << std::endl;
	}
	
}