2024-06-23 17:08:48 +00:00
|
|
|
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
|
|
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
|
|
|
#ifndef CTL_MAP_H_
|
|
|
|
#define CTL_MAP_H_
|
Introduce more CTL content
This change introduces accumulate, addressof, advance, all_of, distance,
array, enable_if, allocator_traits, back_inserter, bad_alloc, is_signed,
any_of, copy, exception, fill, fill_n, is_same, is_same_v, out_of_range,
lexicographical_compare, is_integral, uninitialized_fill_n, is_unsigned,
numeric_limits, uninitialized_fill, iterator_traits, move_backward, min,
max, iterator_tag, move_iterator, reverse_iterator, uninitialized_move_n
This change experiments with rewriting the ctl::vector class to make the
CTL design more similar to the STL. So far it has not slowed things down
to have 42 #include lines rather than 2, since it's still almost nothing
compared to LLVM's code. In fact the closer we can flirt with being just
like libcxx, the better chance we might have of discovering exactly what
makes it so slow to compile. It would be an enormous discovery if we can
find one simple trick to solving the issue there instead.
This also fixes a bug in `ctl::string(const string &s)` when `s` is big.
2024-06-28 05:18:55 +00:00
|
|
|
#include "out_of_range.h"
|
2024-06-23 17:08:48 +00:00
|
|
|
#include "set.h"
|
|
|
|
|
|
|
|
namespace ctl {
|
|
|
|
|
|
|
|
template<typename Key, typename Value, typename Compare = ctl::less<Key>>
|
|
|
|
class map
|
|
|
|
{
|
|
|
|
class EntryCompare
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit EntryCompare(Compare comp = Compare()) : comp_(comp)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()(const ctl::pair<const Key, Value>& lhs,
|
|
|
|
const ctl::pair<const Key, Value>& rhs) const
|
|
|
|
{
|
|
|
|
return comp_(lhs.first, rhs.first);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Compare comp_;
|
|
|
|
};
|
|
|
|
|
|
|
|
ctl::set<ctl::pair<const Key, Value>, EntryCompare> data_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
using key_type = Key;
|
|
|
|
using mapped_type = Value;
|
|
|
|
using value_type = ctl::pair<const Key, Value>;
|
|
|
|
using size_type = typename ctl::set<value_type, EntryCompare>::size_type;
|
|
|
|
using difference_type =
|
|
|
|
typename ctl::set<value_type, EntryCompare>::difference_type;
|
|
|
|
using key_compare = Compare;
|
|
|
|
using value_compare = EntryCompare;
|
|
|
|
using iterator = typename ctl::set<value_type, EntryCompare>::iterator;
|
|
|
|
using const_iterator =
|
|
|
|
typename ctl::set<value_type, EntryCompare>::const_iterator;
|
|
|
|
using reverse_iterator =
|
|
|
|
typename ctl::set<value_type, EntryCompare>::reverse_iterator;
|
|
|
|
using const_reverse_iterator =
|
|
|
|
typename ctl::set<value_type, EntryCompare>::const_reverse_iterator;
|
|
|
|
|
|
|
|
map() : data_(EntryCompare())
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit map(const Compare& comp) : data_(EntryCompare(comp))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
map(const map& other) = default;
|
|
|
|
map(map&& other) noexcept = default;
|
|
|
|
map(std::initializer_list<value_type> init, const Compare& comp = Compare())
|
|
|
|
: data_(init, EntryCompare(comp))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename InputIt>
|
|
|
|
map(InputIt first, InputIt last, const Compare& comp = Compare())
|
|
|
|
: data_(first, last, EntryCompare(comp))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
map& operator=(const map& other) = default;
|
|
|
|
map& operator=(map&& other) noexcept = default;
|
|
|
|
map& operator=(std::initializer_list<value_type> ilist)
|
|
|
|
{
|
|
|
|
data_ = ilist;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator begin() noexcept
|
|
|
|
{
|
|
|
|
return data_.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator begin() const noexcept
|
|
|
|
{
|
|
|
|
return data_.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator cbegin() const noexcept
|
|
|
|
{
|
|
|
|
return data_.cbegin();
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator end() noexcept
|
|
|
|
{
|
|
|
|
return data_.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator end() const noexcept
|
|
|
|
{
|
|
|
|
return data_.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator cend() const noexcept
|
|
|
|
{
|
|
|
|
return data_.cend();
|
|
|
|
}
|
|
|
|
|
|
|
|
reverse_iterator rbegin() noexcept
|
|
|
|
{
|
|
|
|
return data_.rbegin();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_reverse_iterator rbegin() const noexcept
|
|
|
|
{
|
|
|
|
return data_.rbegin();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_reverse_iterator crbegin() const noexcept
|
|
|
|
{
|
|
|
|
return data_.crbegin();
|
|
|
|
}
|
|
|
|
|
|
|
|
reverse_iterator rend() noexcept
|
|
|
|
{
|
|
|
|
return data_.rend();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_reverse_iterator rend() const noexcept
|
|
|
|
{
|
|
|
|
return data_.rend();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_reverse_iterator crend() const noexcept
|
|
|
|
{
|
|
|
|
return data_.crend();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty() const noexcept
|
|
|
|
{
|
|
|
|
return data_.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_type size() const noexcept
|
|
|
|
{
|
|
|
|
return data_.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_type max_size() const noexcept
|
|
|
|
{
|
|
|
|
return data_.max_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
Value& operator[](const Key& key)
|
|
|
|
{
|
|
|
|
return ((data_.insert(make_pair(key, Value()))).first)->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value& operator[](Key&& key)
|
|
|
|
{
|
|
|
|
return ((data_.insert(make_pair(ctl::move(key), Value()))).first)
|
|
|
|
->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value& at(const Key& key)
|
|
|
|
{
|
|
|
|
auto it = find(key);
|
|
|
|
if (it == end())
|
2024-06-30 09:26:38 +00:00
|
|
|
throw ctl::out_of_range();
|
2024-06-23 17:08:48 +00:00
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value& at(const Key& key) const
|
|
|
|
{
|
|
|
|
auto it = find(key);
|
|
|
|
if (it == end())
|
2024-06-30 09:26:38 +00:00
|
|
|
throw ctl::out_of_range();
|
2024-06-23 17:08:48 +00:00
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctl::pair<iterator, bool> insert(const value_type& value)
|
|
|
|
{
|
|
|
|
return data_.insert(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ctl::pair<iterator, bool> insert(value_type&& value)
|
|
|
|
{
|
|
|
|
return data_.insert(ctl::move(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename P>
|
|
|
|
ctl::pair<iterator, bool> insert(P&& value)
|
|
|
|
{
|
|
|
|
return data_.insert(value_type(ctl::forward<P>(value)));
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator insert(const_iterator hint, const value_type& value)
|
|
|
|
{
|
|
|
|
return data_.insert(hint, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator insert(const_iterator hint, value_type&& value)
|
|
|
|
{
|
|
|
|
return data_.insert(hint, ctl::move(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename P>
|
|
|
|
iterator insert(const_iterator hint, P&& value)
|
|
|
|
{
|
|
|
|
return data_.insert(hint, value_type(ctl::forward<P>(value)));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename InputIt>
|
|
|
|
void insert(InputIt first, InputIt last)
|
|
|
|
{
|
|
|
|
data_.insert(first, last);
|
|
|
|
}
|
|
|
|
|
|
|
|
void insert(std::initializer_list<value_type> ilist)
|
|
|
|
{
|
|
|
|
data_.insert(ilist);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename... Args>
|
|
|
|
ctl::pair<iterator, bool> emplace(Args&&... args)
|
|
|
|
{
|
|
|
|
return data_.emplace(ctl::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename... Args>
|
|
|
|
iterator emplace_hint(const_iterator hint, Args&&... args)
|
|
|
|
{
|
|
|
|
return data_.emplace_hint(hint, ctl::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator erase(const_iterator pos)
|
|
|
|
{
|
|
|
|
return data_.erase(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator erase(const_iterator first, const_iterator last)
|
|
|
|
{
|
|
|
|
return data_.erase(first, last);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_type erase(const Key& key)
|
|
|
|
{
|
|
|
|
return data_.erase(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(map& other) noexcept
|
|
|
|
{
|
|
|
|
data_.swap(other.data_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear() noexcept
|
|
|
|
{
|
|
|
|
data_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator find(const Key& key)
|
|
|
|
{
|
|
|
|
return data_.find(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator find(const Key& key) const
|
|
|
|
{
|
|
|
|
return data_.find(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
size_type count(const Key& key) const
|
|
|
|
{
|
|
|
|
return data_.count(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator lower_bound(const Key& key)
|
|
|
|
{
|
|
|
|
return data_.lower_bound(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator lower_bound(const Key& key) const
|
|
|
|
{
|
|
|
|
return data_.lower_bound(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator upper_bound(const Key& key)
|
|
|
|
{
|
|
|
|
return data_.upper_bound(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator upper_bound(const Key& key) const
|
|
|
|
{
|
|
|
|
return data_.upper_bound(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
ctl::pair<iterator, iterator> equal_range(const Key& key)
|
|
|
|
{
|
|
|
|
return data_.equal_range(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
ctl::pair<const_iterator, const_iterator> equal_range(const Key& key) const
|
|
|
|
{
|
|
|
|
return data_.equal_range(make_pair(key, Value()));
|
|
|
|
}
|
|
|
|
|
|
|
|
key_compare key_comp() const
|
|
|
|
{
|
|
|
|
return data_.value_comp().comp;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_compare value_comp() const
|
|
|
|
{
|
|
|
|
return data_.value_comp();
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator==(const map& lhs, const map& rhs)
|
|
|
|
{
|
|
|
|
return lhs.data_ == rhs.data_;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator!=(const map& lhs, const map& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs == rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator<(const map& lhs, const map& rhs)
|
|
|
|
{
|
|
|
|
return lhs.data_ < rhs.data_;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator<=(const map& lhs, const map& rhs)
|
|
|
|
{
|
|
|
|
return !(rhs < lhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator>(const map& lhs, const map& rhs)
|
|
|
|
{
|
|
|
|
return rhs < lhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator>=(const map& lhs, const map& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs < rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend void swap(map& lhs, map& rhs) noexcept
|
|
|
|
{
|
|
|
|
lhs.swap(rhs);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace ctl
|
|
|
|
|
|
|
|
#endif // CTL_MAP_H_
|