#include <algorithm>
#include <iostream>
#include <iterator>
#include <tuple>
#include <vector>

template<typename T>
struct in_situ_pair
: std::iterator<std::forward_iterator_tag, std::pair<T, T>> {

	using pair = std::pair<T, T>;

	in_situ_pair(std::vector<T>& cont, std::size_t idx)
	: cont_(cont), index_{ idx }
	{ }

	pair operator*() const {
		return { cont_[index_], cont_[(index_ + 1) % cont_.size()] };
	}

	in_situ_pair& operator++() {
		++index_;
		return *this;
	}

	bool operator==(const pair& r) const {
		const pair l = operator*();
		return 	(l.first == r.first && l.second == r.second)
				|| (l.first == r.second && l.second == r.first);
	}

	bool operator==(const in_situ_pair& o) const {
		return (index_ == o.index_);
	}

	bool operator!=(const in_situ_pair& o) const {
		return !(*this == o);
	}
public:
	friend bool operator==(const pair& l, const in_situ_pair& r) {
		return (r == l);
	}
private:
	std::vector<T>& cont_;
	std::size_t index_;
};

template<typename T>
using pair_of = std::pair<T, T>;

template<typename T>
std::ostream & operator <<(std::ostream & stream, const pair_of<T>& pair) {
	return stream << '[' << pair.first << ", " << pair.second << ']';
}

namespace in_situ {
	template<typename T>
	in_situ_pair<T> begin(std::vector<T>& cont) { return { cont, 0 }; }

	template<typename T>
	in_situ_pair<T> end(std::vector<T>& cont) { return { cont, cont.size() }; }

	template<typename T>
	in_situ_pair<T> at(std::vector<T>& cont, std::size_t i) { return { cont, i }; }
}

int main() {
	std::vector<int>
		v1 {0 ,1, 2, 3, 4, 5},
		v2 {4, 8, 6, 2, 1, 5, 0, 3};

	for(std::size_t i = 0; i < v1.size(); ++i) {
		auto pos = std::find(in_situ::begin(v2), in_situ::end(v2), in_situ::at(v1, i));
		if(pos != in_situ::end(v2)) {
			std::cout << "common: " << *pos << std::endl;
		}
	}
}