Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
set.hpp 4.36 KiB
/*
 * set.hpp
 *
 * Created on: Apr 1, 2013
 * Author: Jan Travnicek
 */

#ifndef __SET_HPP_
#define __SET_HPP_

#include <set>
#include <ostream>
#include <sstream>
#include <string>

#include "compare.hpp"
#include "allocFix.hpp"

namespace ext {

template < typename T, typename Cmp = std::less < >, typename Alloc = std::allocator < T > >
class set : public std::set < T, Cmp, Alloc >, AllocFix < Alloc > {
public:
	using std::set < T, Cmp, Alloc >::set;
	using std::set < T, Cmp, Alloc >::operator =;
#ifndef __clang__
	set ( ) noexcept : std::set < T, Cmp, Alloc > ( ) {
	}

	set ( const set & other ) = default;

	set ( set && other ) = default;

	set & operator = ( set && other ) = default;

	set & operator = ( const set & other ) = default;
#endif
};

template< class T, class ... Ts >
std::ostream& operator<<(std::ostream& out, const ext::set<T, Ts ...>& list) {
	out << "{";

	bool first = true;
	for(const T& item : list) {
		if(!first) out << ", ";
		first = false;
		out << item;
	}

	out << "}";
	return out;
}

template<class T, class ... Ts>
struct compare < ext::set < T, Ts ... > > {
	int operator()(const ext::set<T, Ts ...>& first, const ext::set<T, Ts ...>& second) const {
		if(first.size() < second.size()) return -1;
		if(first.size() > second.size()) return 1;

		static compare<typename std::decay < T >::type > comp;
		for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); ++iterF, ++iterS) {
			int res = comp(*iterF, *iterS);
			if(res != 0) return res;
		}
		return 0;
	}
};

template < class T, class ... Ts >
std::string to_string ( const ext::set < T, Ts ... > & value ) {
	std::stringstream ss;
	ss << value;
	return ss.str();
}

template <class Iterator>
class set_move_iterator {
	Iterator current;

public:
	typedef Iterator iterator_type;
	typedef typename std::iterator_traits<Iterator>::iterator_category iterator_category;
	typedef typename std::iterator_traits<Iterator>::value_type        value_type;
	typedef Iterator pointer;
	typedef value_type&& reference;

	explicit set_move_iterator() {
	}

	explicit set_move_iterator (Iterator it) : current(it) {
	}

	set_move_iterator (const set_move_iterator<Iterator>& it) : current(it.current) {
	}

	set_move_iterator& operator= (const set_move_iterator<Iterator>& it) {
		current = it.current;
	}

	iterator_type base() const {
		return current;
	}

	pointer operator->() const {
		return current;
	}

	reference operator*() const {
		return std::move(const_cast<value_type&>(*current));
	}

	set_move_iterator& operator++() {
		++current;
		return *this;
	}

	set_move_iterator& operator--() {
		--current;
		return *this;
	}

	set_move_iterator operator++(int) {
		set_move_iterator temp = *this;
		++current;
		return temp;
	}

	set_move_iterator operator--(int) {
		set_move_iterator temp = *this;
		--current;
		return temp;
	}

	bool operator== (const set_move_iterator<Iterator>& other) {
		return this->current == other.current;
	}

	bool operator!= (const set_move_iterator<Iterator>& other) {
		return ! ( *this == other );
	}

};

template<class Iterator>
set_move_iterator<Iterator> make_set_move_iterator (Iterator it) {
	return set_move_iterator<Iterator>(it);
}

template<class T>
class moveable_set_ref {
	ext::set < T > & theSet;
public:
	moveable_set_ref ( ext::set < T > & param) : theSet(param) {}

	set_move_iterator < typename ext::set < T >::iterator > begin() {
		return make_set_move_iterator(theSet.begin());
	}

	set_move_iterator < typename ext::set < T >::iterator > end() {
		return make_set_move_iterator(theSet.end());
	}
};

template<class T>
moveable_set_ref < T > make_moveable_set ( ext::set < T > & set) {
	return moveable_set_ref<T>(set);
}

template<class T>
class moveable_set {
	ext::set < T > theSet;
public:
	moveable_set( ext::set < T > && param) : theSet ( std::move ( param ) ) {}

	set_move_iterator<typename ext::set < T >::iterator > begin() {
		return make_set_move_iterator(theSet.begin());
	}

	set_move_iterator < typename ext::set < T >::iterator > end() {
		return make_set_move_iterator(theSet.end());
	}
};

template<class T>
moveable_set < T > make_moveable_set ( ext::set < T > && set) {
	return moveable_set<T>(std::move(set));
}

template < class T >
ext::set < T > operator +( const ext::set < T > & first, const ext::set < T > & second ) {
	ext::set < T > res ( first );

	res.insert ( second.begin ( ), second.end ( ) );
	return res;
}

} /* namespace ext */

#endif /* __SET_HPP_ */