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

template<typename Pair>
class pair_generator {
public:
	explicit pair_generator(std::vector<Pair>& cont)
	: cont_(cont)
	{ }

	template<typename T>
	bool operator()(T l, T r) {
		cont_.emplace_back(r, l);
		return true;
	}
private:
	std::vector<Pair>& cont_;
};

template<typename Pair>
struct position_independant_compare {

	explicit position_independant_compare(const Pair& pair)
	: pair_(pair)
	{ }

	bool operator()(const Pair & p) const {
		return (p.first == pair_.first && p.second == pair_.second) || (p.first == pair_.second && p.second == pair_.first);
	}
private:
	const Pair& pair_;
};

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 << ']';
}

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

	std::vector<pair_of<int> >
		p1 { },
		p2 { };

	// generate our pairs
	std::sort(v1.begin(), v1.end(), pair_generator<pair_of<int>>{ p1 });
	std::sort(v2.begin(), v2.end(), pair_generator<pair_of<int>>{ p2 });

	// account for the fact that the first and last element are a pair too
	p1.emplace_back(p1.front().first, p1.back().second);
	p2.emplace_back(p2.front().first, p2.back().second);

	std::cout << "pairs for vector 1" << std::endl;
	for(const auto & p : p1) { std::cout << p << std::endl; }

	std::cout << std::endl << "pairs for vector 2" << std::endl;
	for(const auto & p : p2) { std::cout << p << std::endl; }

	std::cout << std::endl << "pairs shared between vector 1 and vector 2" << std::endl;
	for(const auto & p : p1) {
		const auto pos = std::find_if(p2.begin(), p2.end(), position_independant_compare<pair_of<int>>{ p });
		if(pos != p2.end()) {
			std::cout << p << std::endl;
		}
	}
}