v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
322
source/core/StarSet.hpp
Normal file
322
source/core/StarSet.hpp
Normal file
|
@ -0,0 +1,322 @@
|
|||
#ifndef STAR_SET_HPP
|
||||
#define STAR_SET_HPP
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "StarFlatHashSet.hpp"
|
||||
#include "StarList.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
STAR_EXCEPTION(SetException, StarException);
|
||||
|
||||
template <typename BaseSet>
|
||||
class SetMixin : public BaseSet {
|
||||
public:
|
||||
typedef BaseSet Base;
|
||||
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
|
||||
typedef typename Base::value_type value_type;
|
||||
|
||||
using Base::Base;
|
||||
|
||||
List<value_type> values() const;
|
||||
|
||||
bool contains(value_type const& v) const;
|
||||
|
||||
bool add(value_type const& v);
|
||||
|
||||
// Like add, but always adds new value, potentially replacing another equal
|
||||
// (comparing equal, may not be actually equal) value. Returns whether an
|
||||
// existing value was replaced.
|
||||
bool replace(value_type v);
|
||||
|
||||
template <typename Container>
|
||||
void addAll(Container const& s);
|
||||
|
||||
bool remove(value_type const& v);
|
||||
|
||||
template <typename Container>
|
||||
void removeAll(Container const& s);
|
||||
|
||||
value_type first();
|
||||
Maybe<value_type> maybeFirst();
|
||||
value_type takeFirst();
|
||||
Maybe<value_type> maybeTakeFirst();
|
||||
|
||||
value_type last();
|
||||
Maybe<value_type> maybeLast();
|
||||
value_type takeLast();
|
||||
Maybe<value_type> maybeTakeLast();
|
||||
|
||||
bool hasIntersection(SetMixin const& s) const;
|
||||
};
|
||||
|
||||
template <typename BaseSet>
|
||||
std::ostream& operator<<(std::ostream& os, SetMixin<BaseSet> const& set);
|
||||
|
||||
template <typename Value, typename Compare = std::less<Value>, typename Allocator = std::allocator<Value>>
|
||||
class Set : public SetMixin<std::set<Value, Compare, Allocator>> {
|
||||
public:
|
||||
typedef SetMixin<std::set<Value, Compare, Allocator>> Base;
|
||||
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
|
||||
typedef typename Base::value_type value_type;
|
||||
|
||||
template <typename Container>
|
||||
static Set from(Container const& c);
|
||||
|
||||
using Base::Base;
|
||||
|
||||
// Returns set of elements that are in this set and the given set.
|
||||
Set intersection(Set const& s) const;
|
||||
Set intersection(Set const& s, std::function<bool(Value const&, Value const&)> compare) const;
|
||||
|
||||
// Returns elements in this set that are not in the given set
|
||||
Set difference(Set const& s) const;
|
||||
Set difference(Set const& s, std::function<bool(Value const&, Value const&)> compare) const;
|
||||
|
||||
// Returns elements in either this set or the given set
|
||||
Set combination(Set const& s) const;
|
||||
};
|
||||
|
||||
template <typename BaseSet>
|
||||
class HashSetMixin : public SetMixin<BaseSet> {
|
||||
public:
|
||||
typedef SetMixin<BaseSet> Base;
|
||||
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
|
||||
typedef typename Base::value_type value_type;
|
||||
|
||||
template <typename Container>
|
||||
static HashSetMixin from(Container const& c);
|
||||
|
||||
using Base::Base;
|
||||
|
||||
HashSetMixin intersection(HashSetMixin const& s) const;
|
||||
HashSetMixin difference(HashSetMixin const& s) const;
|
||||
HashSetMixin combination(HashSetMixin const& s) const;
|
||||
};
|
||||
|
||||
template <typename Value, typename Hash = hash<Value>, typename Equals = std::equal_to<Value>, typename Allocator = std::allocator<Value>>
|
||||
using HashSet = HashSetMixin<FlatHashSet<Value, Hash, Equals, Allocator>>;
|
||||
|
||||
template <typename Value, typename Hash = hash<Value>, typename Equals = std::equal_to<Value>, typename Allocator = std::allocator<Value>>
|
||||
using StableHashSet = HashSetMixin<std::unordered_set<Value, Hash, Equals, Allocator>>;
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::values() const -> List<value_type> {
|
||||
return List<value_type>(Base::begin(), Base::end());
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
bool SetMixin<BaseSet>::contains(value_type const& v) const {
|
||||
return Base::find(v) != Base::end();
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
bool SetMixin<BaseSet>::add(value_type const& v) {
|
||||
return Base::insert(v).second;
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
bool SetMixin<BaseSet>::replace(value_type v) {
|
||||
bool replaced = remove(v);
|
||||
Base::insert(move(v));
|
||||
return replaced;
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
template <typename Container>
|
||||
void SetMixin<BaseSet>::addAll(Container const& s) {
|
||||
return Base::insert(s.begin(), s.end());
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
bool SetMixin<BaseSet>::remove(value_type const& v) {
|
||||
return Base::erase(v) != 0;
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
template <typename Container>
|
||||
void SetMixin<BaseSet>::removeAll(Container const& s) {
|
||||
for (auto const& v : s)
|
||||
remove(v);
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::first() -> value_type {
|
||||
if (Base::empty())
|
||||
throw SetException("first called on empty set");
|
||||
return *Base::begin();
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::maybeFirst() -> Maybe<value_type> {
|
||||
if (Base::empty())
|
||||
return {};
|
||||
return *Base::begin();
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::takeFirst() -> value_type {
|
||||
if (Base::empty())
|
||||
throw SetException("takeFirst called on empty set");
|
||||
auto i = Base::begin();
|
||||
value_type v = move(*i);
|
||||
Base::erase(i);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::maybeTakeFirst() -> Maybe<value_type> {
|
||||
if (Base::empty())
|
||||
return {};
|
||||
auto i = Base::begin();
|
||||
value_type v = move(*i);
|
||||
Base::erase(i);
|
||||
return move(v);
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::last() -> value_type {
|
||||
if (Base::empty())
|
||||
throw SetException("last called on empty set");
|
||||
return *prev(Base::end());
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::maybeLast() -> Maybe<value_type> {
|
||||
if (Base::empty())
|
||||
return {};
|
||||
return *prev(Base::end());
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::takeLast() -> value_type {
|
||||
if (Base::empty())
|
||||
throw SetException("takeLast called on empty set");
|
||||
auto i = prev(Base::end());
|
||||
value_type v = move(*i);
|
||||
Base::erase(i);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
auto SetMixin<BaseSet>::maybeTakeLast() -> Maybe<value_type> {
|
||||
if (Base::empty())
|
||||
return {};
|
||||
auto i = prev(Base::end());
|
||||
value_type v = move(*i);
|
||||
Base::erase(i);
|
||||
return move(v);
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
bool SetMixin<BaseSet>::hasIntersection(SetMixin const& s) const {
|
||||
for (auto const& v : s) {
|
||||
if (contains(v)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename BaseSet>
|
||||
std::ostream& operator<<(std::ostream& os, SetMixin<BaseSet> const& set) {
|
||||
os << "(";
|
||||
for (auto i = set.begin(); i != set.end(); ++i) {
|
||||
if (i != set.begin())
|
||||
os << ", ";
|
||||
os << *i;
|
||||
}
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename Value, typename Compare, typename Allocator>
|
||||
template <typename Container>
|
||||
Set<Value, Compare, Allocator> Set<Value, Compare, Allocator>::from(Container const& c) {
|
||||
return Set(c.begin(), c.end());
|
||||
}
|
||||
|
||||
template <typename Value, typename Compare, typename Allocator>
|
||||
Set<Value, Compare, Allocator> Set<Value, Compare, Allocator>::intersection(Set const& s) const {
|
||||
Set res;
|
||||
std::set_intersection(Base::begin(), Base::end(), s.begin(), s.end(), std::inserter(res, res.end()));
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Value, typename Compare, typename Allocator>
|
||||
Set<Value, Compare, Allocator> Set<Value, Compare, Allocator>::intersection(Set const& s, std::function<bool(Value const&, Value const&)> compare) const {
|
||||
Set res;
|
||||
std::set_intersection(Base::begin(), Base::end(), s.begin(), s.end(), std::inserter(res, res.end()), compare);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Value, typename Compare, typename Allocator>
|
||||
Set<Value, Compare, Allocator> Set<Value, Compare, Allocator>::difference(Set const& s) const {
|
||||
Set res;
|
||||
std::set_difference(Base::begin(), Base::end(), s.begin(), s.end(), std::inserter(res, res.end()));
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Value, typename Compare, typename Allocator>
|
||||
Set<Value, Compare, Allocator> Set<Value, Compare, Allocator>::difference(Set const& s, std::function<bool(Value const&, Value const&)> compare) const {
|
||||
Set res;
|
||||
std::set_difference(Base::begin(), Base::end(), s.begin(), s.end(), std::inserter(res, res.end()), compare);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Value, typename Compare, typename Allocator>
|
||||
Set<Value, Compare, Allocator> Set<Value, Compare, Allocator>::combination(Set const& s) const {
|
||||
Set ret(*this);
|
||||
ret.addAll(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
template <typename Container>
|
||||
HashSetMixin<BaseMap> HashSetMixin<BaseMap>::from(Container const& c) {
|
||||
return HashSetMixin(c.begin(), c.end());
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
HashSetMixin<BaseMap> HashSetMixin<BaseMap>::intersection(HashSetMixin const& s) const {
|
||||
// Can't use std::set_intersection, since not sorted, naive version is fine.
|
||||
HashSetMixin ret;
|
||||
for (auto const& e : s) {
|
||||
if (contains(e))
|
||||
ret.add(e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
HashSetMixin<BaseMap> HashSetMixin<BaseMap>::difference(HashSetMixin const& s) const {
|
||||
// Can't use std::set_difference, since not sorted, naive version is fine.
|
||||
HashSetMixin ret;
|
||||
for (auto const& e : *this) {
|
||||
if (!s.contains(e))
|
||||
ret.add(e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
HashSetMixin<BaseMap> HashSetMixin<BaseMap>::combination(HashSetMixin const& s) const {
|
||||
HashSetMixin ret(*this);
|
||||
ret.addAll(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue