friend PIBinaryStream & operator<<(PIBinaryStream
& s, const PISet & v);
template
friend PIBinaryStream & operator>>(PIBinaryStream
& s, PISet & v);
public:
//! \~english Constructs an empty set.
//! \~russian Создает пустое множество.
PISet() {}
//! \~english Constructs a set with one element `value`.
//! \~russian Создает множество с одним элементом `value`.
explicit PISet(const T & value) { _CSet::insert(value, 0); }
//! \~english Constructs a set with two elements `v0` and `v1`.
//! \~russian Создает множество с двумя элементами `v0` и `v1`.
PISet(const T & v0, const T & v1) {
_CSet::insert(v0, 0);
_CSet::insert(v1, 0);
}
//! \~english Constructs a set with three elements `v0`, `v1` and `v2`.
//! \~russian Создает множество с тремя элементами `v0`, `v1` и `v2`.
PISet(const T & v0, const T & v1, const T & v2) {
_CSet::insert(v0, 0);
_CSet::insert(v1, 0);
_CSet::insert(v2, 0);
}
//! \~english Constructs a set with four elements `v0`, `v1`, `v2` and `v3`.
//! \~russian Создает множество с четырьмя элементами `v0`, `v1`, `v2` и `v3`.
PISet(const T & v0, const T & v1, const T & v2, const T & v3) {
_CSet::insert(v0, 0);
_CSet::insert(v1, 0);
_CSet::insert(v2, 0);
_CSet::insert(v3, 0);
}
class const_iterator {
friend class PISet;
private:
inline const_iterator(const PISet * v, ssize_t p): parent(v), pos(p) {}
const PISet * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_iterator(): parent(0), pos(0) {}
inline const T & operator*() const { return parent->pim_index[pos].key; }
inline const T & operator->() const { return parent->pim_index[pos].key; }
inline const_iterator & operator++() {
++pos;
return *this;
}
inline const_iterator operator++(int) {
const auto tmp = *this;
++*this;
return tmp;
}
inline const_iterator & operator--() {
--pos;
return *this;
}
inline const_iterator operator--(int) {
const auto tmp = *this;
--*this;
return tmp;
}
inline const_iterator & operator+=(const const_iterator & it) {
pos += it.pos;
return *this;
}
inline const_iterator & operator+=(size_t p) {
pos += p;
return *this;
}
inline const_iterator & operator-=(const const_iterator & it) {
pos -= it.pos;
return *this;
}
inline const_iterator & operator-=(size_t p) {
pos -= p;
return *this;
}
friend inline const_iterator operator-(size_t p, const const_iterator & it) { return it - p; }
friend inline const_iterator operator-(const const_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; }
friend inline const_iterator operator+(size_t p, const const_iterator & it) { return it + p; }
friend inline const_iterator operator+(const const_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator==(const const_iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const const_iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; }
};
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator end() const { return const_iterator(this, _CSet::size()); }
//! \~english Constructs a set from a vector of elements.
//! \~russian Создает множество из вектора элементов.
explicit PISet(const PIVector & values) {
if (values.isEmpty()) return;
for (int i = 0; i < values.size_s(); ++i) {
_CSet::insert(values[i], 0);
}
}
//! \~english Constructs a set from a deque of elements.
//! \~russian Создает множество из deque элементов.
explicit PISet(const PIDeque & values) {
if (values.isEmpty()) return;
for (int i = 0; i < values.size_s(); ++i) {
_CSet::insert(values[i], 0);
}
}
typedef T key_type;
//! \~english Inserts element `t` into the set.
//! \~russian Вставляет элемент `t` в множество.
PISet & operator<<(const T & t) {
_CSet::insert(t, 0);
return *this;
}
PISet & operator<<(T && t) {
_CSet::insert(std::move(t), 0);
return *this;
}
PISet & operator<<(const PISet & other) {
(*(_CSet *)this) << *((_CSet *)&other);
return *this;
}
//! \~english Tests if element `t` exists in the set.
//! \~russian Проверяет наличие элемента `t` в множестве.
inline bool contains(const T & t) const { return _CSet::contains(t); }
//! \~english Tests if element `t` exists in the set.
//! \~russian Проверяет наличие элемента `t` в множестве.
bool operator[](const T & t) const { return _CSet::contains(t); }
//! \~english Removes element `t` from the set.
//! \~russian Удаляет элемент `t` из множества.
PISet & remove(const T & t) {
_CSet::remove(t);
return *this;
}
//! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet & unite(const PISet & v) {
for (const auto & i: v)
_CSet::insert(i, 0);
return *this;
}
//! \~english Returns the difference of this set and set `v`.
//! \~russian Возвращает разность этого множества и множества `v`.
PISet & subtract(const PISet & v) {
for (const auto & i: v)
_CSet::remove(i);
return *this;
}
//! \~english Returns the intersection of this set with set `v`.
//! \~russian Возвращает пересечение этого множества с множеством `v`.
PISet & intersect(const PISet & v) {
_CSet::removeWhere([&v](const T & k, uchar) { return !v.contains(k); });
return *this;
}
//! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet & operator+=(const PISet & v) { return unite(v); }
//! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet & operator|=(const PISet & v) { return unite(v); }
//! \~english Returns the difference of this set and set `v`.
//! \~russian Возвращает разность этого множества и множества `v`.
PISet & operator-=(const PISet & v) { return subtract(v); }
//! \~english Returns the intersection of this set with set `v`.
//! \~russian Возвращает пересечение этого множества с множеством `v`.
PISet & operator&=(const PISet & v) { return intersect(v); }
//! \~english Converts the set to a vector.
//! \~russian Преобразует множество в вектор.
PIVector toVector() const {
PIVector ret;
for (const auto & i: *this)
ret << i;
return ret;
}
//! \~english Converts the set to a deque.
//! \~russian Преобразует множество в deque.
PIDeque toDeque() const {
PIDeque ret;
for (const auto & i: *this)
ret << i;
return ret;
}
};
//! \~english Returns the union of two sets.
//! \~russian Возвращает объединение двух множеств.
template
PISet operator+(const PISet & v0, const PISet & v1) {
PISet ret(v0);
ret.unite(v1);
return ret;
}
//! \~english Returns the difference of two sets.
//! \~russian Возвращает разность двух множеств.
template
PISet operator-(const PISet & v0, const PISet & v1) {
PISet ret(v0);
ret.subtract(v1);
return ret;
}
//! \~english Returns the union of two sets.
//! \~russian Возвращает объединение двух множеств.
template
PISet operator|(const PISet & v0, const PISet & v1) {
PISet ret(v0);
ret.unite(v1);
return ret;
}
//! \~english Returns the intersection of two sets.
//! \~russian Возвращает пересечение двух множеств.
template
PISet operator&(const PISet & v0, const PISet & v1) {
PISet ret(v0);
ret.intersect(v1);
return ret;
}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template
inline PICout operator<<(PICout s, const PISet & v) {
s.space();
s.saveAndSetControls(0);
s << "{";
bool first = true;
for (const auto & i: v) {
if (!first) s << ", ";
first = false;
s << i;
}
s << "}";
s.restoreControls();
return s;
}
//! \}
#endif // PISET_H