osb/source/core/StarOrderedSet.hpp
Kai Blaschke 431a9c00a5
Fixed a huge amount of Clang warnings
On Linux and macOS, using Clang to compile OpenStarbound produces about 400 MB worth of warnings during the build, making the compiler output unreadable and slowing the build down considerably.

99% of the warnings were unqualified uses of std::move and std::forward, which are now all properly qualified.

Fixed a few other minor warnings about non-virtual destructors and some uses of std::move preventing copy elision on temporary objects.

Most remaining warnings are now unused parameters.
2024-02-19 16:55:19 +01:00

434 lines
15 KiB
C++

#ifndef STAR_ORDERED_SET_HPP
#define STAR_ORDERED_SET_HPP
#include <map>
#include "StarFlatHashMap.hpp"
#include "StarSet.hpp"
#include "StarList.hpp"
namespace Star {
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
class OrderedSetWrapper {
public:
typedef Value value_type;
typedef LinkedList<value_type, typename Allocator::template rebind<value_type>::other> OrderType;
typedef Map<
std::reference_wrapper<value_type const>, typename OrderType::const_iterator, Args...,
typename Allocator::template rebind<pair<std::reference_wrapper<value_type const> const, typename OrderType::const_iterator>>::other
> MapType;
typedef typename OrderType::const_iterator const_iterator;
typedef const_iterator iterator;
typedef typename OrderType::const_reverse_iterator const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator;
template <typename Collection>
static OrderedSetWrapper from(Collection const& c);
OrderedSetWrapper();
OrderedSetWrapper(OrderedSetWrapper const& set);
template <typename InputIterator>
OrderedSetWrapper(InputIterator beg, InputIterator end);
OrderedSetWrapper(initializer_list<value_type> list);
OrderedSetWrapper& operator=(OrderedSetWrapper const& set);
// Guaranteed to be in order.
List<value_type> values() const;
bool contains(value_type const& v) const;
// add either adds the value to the back, or does not move it from its
// current order.
pair<iterator, bool> insert(value_type const& v);
// like insert, but only returns whether the value was added or not.
bool add(Value const& v);
// Always replaces an existing value with a new value if it exists, and
// always moves to the back.
bool replace(Value const& v);
// Either adds a value to the end of the order, or moves an existing value to
// the back.
bool addBack(Value const& v);
// Either adds a value to the beginning of the order, or moves an existing
// value to the beginning.
bool addFront(Value const& v);
template <typename Container>
void addAll(Container const& c);
iterator toFront(iterator i);
iterator toBack(iterator i);
bool remove(value_type const& v);
template <typename Container>
void removeAll(Container const& c);
void clear();
value_type const& first() const;
value_type const& last() const;
void removeFirst();
void removeLast();
value_type takeFirst();
value_type takeLast();
template <typename Compare>
void sort(Compare comp);
void sort();
size_t empty() const;
size_t size() const;
const_iterator begin() const;
const_iterator end() const;
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
Maybe<size_t> indexOf(value_type const& v) const;
value_type const& at(size_t i) const;
value_type& at(size_t i);
OrderedSetWrapper intersection(OrderedSetWrapper const& s) const;
OrderedSetWrapper difference(OrderedSetWrapper const& s) const;
private:
MapType m_map;
OrderType m_order;
};
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
std::ostream& operator<<(std::ostream& os, OrderedSetWrapper<Map, Value, Allocator, Args...> const& set);
template <typename Value, typename Compare = std::less<Value>, typename Allocator = std::allocator<Value>>
using OrderedSet = OrderedSetWrapper<std::map, Value, Allocator, Compare>;
template <typename Value, typename Hash = Star::hash<Value>, typename Equals = std::equal_to<Value>, typename Allocator = std::allocator<Value>>
using OrderedHashSet = OrderedSetWrapper<FlatHashMap, Value, Allocator, Hash, Equals>;
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Collection>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::from(Collection const& c) -> OrderedSetWrapper {
return OrderedSetWrapper(c.begin(), c.end());
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper() {}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper(OrderedSetWrapper const& set) {
for (auto const& p : set)
add(p);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename InputIterator>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper(InputIterator beg, InputIterator end) {
while (beg != end) {
add(*beg);
++beg;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
OrderedSetWrapper<Map, Value, Allocator, Args...>::OrderedSetWrapper(initializer_list<value_type> list) {
for (value_type const& v : list)
add(v);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::operator=(OrderedSetWrapper const& set) -> OrderedSetWrapper& {
if (this != &set) {
clear();
for (auto const& p : set)
add(p);
}
return *this;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::values() const -> List<value_type> {
List<value_type> values;
for (auto p : *this)
values.append(std::move(p));
return values;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::contains(value_type const& v) const {
return m_map.find(v) != m_map.end();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::insert(value_type const& v) -> pair<iterator, bool> {
auto i = m_map.find(v);
if (i == m_map.end()) {
auto orderIt = m_order.insert(m_order.end(), v);
m_map.insert(typename MapType::value_type(std::cref(*orderIt), orderIt));
return {orderIt, true};
}
return {i->second, false};
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::add(Value const& v) {
return insert(v).second;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::replace(Value const& v) {
bool replaced = remove(v);
add(v);
return replaced;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::addBack(Value const& v) {
auto i = m_map.find(v);
if (i != m_map.end()) {
m_order.splice(m_order.end(), m_order, i->second);
return false;
} else {
iterator orderIt = m_order.insert(m_order.end(), v);
m_map.insert(typename MapType::value_type(std::cref(*orderIt), orderIt));
return true;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::addFront(Value const& v) {
auto i = m_map.find(v);
if (i != m_map.end()) {
m_order.splice(m_order.begin(), m_order, i->second);
return false;
} else {
iterator orderIt = m_order.insert(m_order.end(), v);
m_map.insert(typename MapType::value_type(std::cref(*orderIt), orderIt));
return true;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Container>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::addAll(Container const& c) {
for (auto const& v : c)
add(v);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::toFront(iterator i) -> iterator {
m_order.splice(m_order.begin(), m_order, i);
return m_order.begin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::toBack(iterator i) -> iterator {
m_order.splice(m_order.end(), m_order, i);
return prev(m_order.end());
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
bool OrderedSetWrapper<Map, Value, Allocator, Args...>::remove(value_type const& v) {
auto i = m_map.find(v);
if (i != m_map.end()) {
auto orderIt = i->second;
m_map.erase(i);
m_order.erase(orderIt);
return true;
}
return false;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Container>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::removeAll(Container const& c) {
for (auto const& v : c)
remove(v);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::clear() {
m_map.clear();
m_order.clear();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::first() const -> value_type const& {
if (empty())
throw SetException("first() called on empty OrderedSet");
return *begin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::last() const -> value_type const& {
if (empty())
throw SetException("last() called on empty OrderedSet");
return *(prev(end()));
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::removeFirst() {
if (empty())
throw SetException("OrderedSet::removeFirst() called on empty OrderedSet");
auto i = m_order.begin();
m_map.erase(*i);
m_order.erase(i);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::removeLast() {
if (empty())
throw SetException("OrderedSet::removeLast() called on empty OrderedSet");
auto i = m_order.end();
--i;
m_map.erase(*i);
m_order.erase(i);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::takeFirst() -> value_type {
if (empty())
throw SetException("OrderedSet::takeFirst() called on empty OrderedSet");
auto i = m_order.begin();
m_map.erase(*i);
value_type v = *i;
m_order.erase(i);
return v;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::takeLast() -> value_type {
if (empty())
throw SetException("OrderedSet::takeLast() called on empty OrderedSet");
auto i = m_order.end();
--i;
m_map.erase(*i);
value_type v = *i;
m_order.erase(i);
return v;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
template <typename Compare>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::sort(Compare comp) {
m_order.sort(comp);
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
void OrderedSetWrapper<Map, Value, Allocator, Args...>::sort() {
m_order.sort();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
size_t OrderedSetWrapper<Map, Value, Allocator, Args...>::empty() const {
return m_map.empty();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
size_t OrderedSetWrapper<Map, Value, Allocator, Args...>::size() const {
return m_map.size();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::begin() const -> const_iterator {
return m_order.begin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::end() const -> const_iterator {
return m_order.end();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::rbegin() const -> const_reverse_iterator {
return m_order.rbegin();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::rend() const -> const_reverse_iterator {
return m_order.rend();
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
Maybe<size_t> OrderedSetWrapper<Map, Value, Allocator, Args...>::indexOf(value_type const& v) const {
auto i = m_map.find(v);
if (i == m_map.end())
return {};
return std::distance(begin(), const_iterator(i->second));
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::at(size_t i) const -> value_type const& {
auto it = begin();
std::advance(it, i);
return *it;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::at(size_t i) -> value_type& {
auto it = begin();
std::advance(it, i);
return *it;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::intersection(OrderedSetWrapper const& s) const -> OrderedSetWrapper {
OrderedSetWrapper ret;
for (auto const& e : s) {
if (contains(e))
ret.add(e);
}
return ret;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
auto OrderedSetWrapper<Map, Value, Allocator, Args...>::difference(OrderedSetWrapper const& s) const -> OrderedSetWrapper {
OrderedSetWrapper ret;
for (auto const& e : *this) {
if (!s.contains(e))
ret.add(e);
}
return ret;
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
std::ostream& operator<<(std::ostream& os, OrderedSetWrapper<Map, Value, Allocator, Args...> const& set) {
os << "(";
for (auto i = set.begin(); i != set.end(); ++i) {
if (i != set.begin())
os << ", ";
os << *i;
}
os << ")";
return os;
}
}
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
struct fmt::formatter<Star::OrderedSetWrapper<Map, Value, Allocator, Args...>> : ostream_formatter {};
#endif