* This header defines two classes that very nearly model
* AssociativeContainer (but not quite). These implement set-like and
* map-like behavior on top of a sorted vector, instead of using
* rb-trees like std::set and std::map.
*
* This is potentially useful in cases where the number of elements in
* the set or map is small, or when you want to avoid using more
* memory than necessary and insertions/deletions are much more rare
* than lookups (these classes have O(N) insertions/deletions).
*/*这个头文件定义了两个相近的类,相协调的类,但不相等,在已排好的vector,实现行为像set,map的行为,而不是红黑树,这潜在的好处就是当set和map的元素比较小的时候,当你想避免使用更多的内存,而这的重要性比你插入/删除更多,比查找更少,这些类拥有O(N)现行复杂度的插入删除
如果你对最小化使用内存有兴趣,那么这些类应该支持增长政策参数,不论我们什么时候插入元素,他都会被调用,然后你可以调用reserve(),根据现有的内存使用情况来分配新的内存
*/
* In the interest of using these in conditions where the goal is to
* minimize memory usage, they support a GrowthPolicy parameter, which
* is a class defining a single function called increase_capacity,
* which will be called whenever we are about to insert something: you
* can then decide to call reserve() based on the current capacity()
* and size() of the passed in vector-esque Container type. An
* example growth policy that grows one element at a time:
*
* struct OneAtATimePolicy {
* template<class Container>
* void increase_capacity(Container& c) {
* if (c.size() == c.capacity()) {
* c.reserve(c.size() + 1);
* }
* }
* };
*
* typedef sorted_vector_set<int,
* std::less<int>,
* std::allocator<int>,
* OneAtATimePolicy>
* OneAtATimeIntSet;
*
* Important differences from std::set and std::map:
* - insert() and erase() invalidate iterators and references
* - insert() and erase() are O(N)
* - our iterators model RandomAccessIterator
* - sorted_vector_map::value_type is pair<K,V>, not pair<const K,V>.
* (This is basically because we want to store the value_type in
* std::vector<>, which requires it to be Assignable.)
*/
#pragma once
#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <utility>
#include <vector>
#include <boost/operators.hpp>
#include <boost/bind.hpp>//vs报错
#include <boost/type_traits/is_same.hpp>
namespace folly {
//
namespace detail {
// This wrapper goes around a GrowthPolicy and provides iterator
// preservation(保存) semantics, but only if the growth policy is not the
// default (i.e. nothing).
template<class Policy>
struct growth_policy_wrapper : private Policy {
template<class Container, class Iterator>
Iterator increase_capacity(Container& c, Iterator desired_insertion)
{
typedef typename Container::difference_type diff_t;
diff_t d = desired_insertion - c.begin();
Policy::increase_capacity(c);
return c.begin() + d;
}
};
/*这个类用来封装增长分配的政策,明显政策这里是具有弹性的,针对上面的OneAtATimePolicy
有几点疑问:它用私有继承,我能理解毕竟一个容器是用来用的,不是开源让后人盖楼,从OneAtATimePolicy
用size()和capacity()我能推断出,这是以标准库容器作为参数,
未知:为什么参数是将要插入的位置;为什么没有插入动作(下面解答),却返回插入位置的指针
*/
template<>
struct growth_policy_wrapper<void> {
template<class Container, class Iterator>
Iterator increase_capacity(Container&, Iterator it) {
return it;
}
};
/*这个全特化,看起来就像为空政策做的准备
*/
/*
* This helper returns the distance between two iterators if it is
* possible to figure it out without messing up the range
* (i.e. unless they are InputIterators). Otherwise this returns
* -1.
*/
/*这个助手返回两个迭代器的距离,前提是没有把这两个的范围搞错,例如两个数相等*/
template<class Iterator>
int distance_if_multipass(Iterator first, Iterator last) {
typedef typename std::iterator_traits<Iterator>::iterator_category categ;
if (boost::is_same<categ,std::input_iterator_tag>::value)
return -1;
return std::distance(first, last);
}
//这里把输入溜迭代器除外,应该不能进行减操作
template<class OurContainer, class Vector, class GrowthPolicy>
typename OurContainer::iterator
insert_with_hint(OurContainer& sorted,
Vector& cont,
typename OurContainer::iterator hint,
typename OurContainer::value_type&& value,
GrowthPolicy& po)
{
const typename OurContainer::value_compare& cmp(sorted.value_comp());
if (hint == cont.end() || cmp(value, *hint)) {
if (hint == cont.begin()) {
po.increase_capacity(cont, cont.begin());
//OneAtATimePolicy就是看看有地方没,下面才是真正的插入动作
return cont.insert(cont.begin(), std::move(value));
}
/*这是一种特殊情况,所插位置所在值既比既比value大,且他还插在头部*/
if (cmp(*(hint - 1), value)) {
hint = po.increase_capacity(cont, hint);
return cont.insert(hint, std::move(value));
}
/*他想插在末尾,且前面的值比他小
或者说他满足第二个条件,后面的值比它大,这时再满足这个条件
就又可以不用再调整顺序了
*/
return sorted.insert(std::move(value)).first;
//把上面的vector理解为data members就好
}
if (cmp(*hint, value)) {
if (hint + 1 == cont.end() || cmp(value, *(hint + 1))) {
typename OurContainer::iterator it =
po.increase_capacity(cont, hint + 1);
return cont.insert(it, std::move(value));
}
}
//当插入的值比 将插入位置所在值大,又分了两种情况,最后一个,注意左闭右开
//或者正好将插入位置的后一个位置所在值比插入值大,这样也可以不用重新排序了
// Value and *hint did not compare, so they are equal keys.
return hint;//如果都不符合了,就返回这个迭代器
}
}
//
/**
* A sorted_vector_set is a container similar to std::set<>, but
* implemented as as a sorted array with std::vector<>.
*
* @param class T Data type to store
* @param class Compare Comparison function that imposes a
* strict weak ordering over instances of T
* @param class Allocator allocation policy
* @param class GrowthPolicy policy object to control growth
*
* @author Aditya Agarwal <aditya@fb.com>
* @author Akhil Wable <akhil@fb.com>
* @author Jordan DeLong <delong.j@fb.com>
*/
template<class T,
class Compare = std::less<T>,
class Allocator = std::allocator<T>,
class GrowthPolicy = void>
class sorted_vector_set
: boost::totally_ordered1<
sorted_vector_set<T,Compare,Allocator,GrowthPolicy>
, detail::growth_policy_wrapper<GrowthPolicy> >
{
typedef std::vector<T,Allocator> ContainerT;
detail::growth_policy_wrapper<GrowthPolicy>&
get_growth_policy() { return *this; }
public:
typedef T value_type;
typedef T key_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef typename ContainerT::pointer pointer;
typedef typename ContainerT::reference reference;
typedef typename ContainerT::const_reference const_reference;
/*
* XXX: Our normal iterator ought to also be a constant iterator
* (cf. Defect Report 103 for std::set), but this is a bit more of a
* pain.
*/
typedef typename ContainerT::iterator iterator;
typedef typename ContainerT::const_iterator const_iterator;
typedef typename ContainerT::difference_type difference_type;
typedef typename ContainerT::size_type size_type;
typedef typename ContainerT::reverse_iterator reverse_iterator;
typedef typename ContainerT::const_reverse_iterator const_reverse_iterator;
explicit sorted_vector_set(const Compare& comp = Compare(),
const Allocator& alloc = Allocator())
: m_(comp, alloc)
{}
template<class InputIterator>
explicit sorted_vector_set(
InputIterator first,
InputIterator last,
const Compare& comp = Compare(),
const Allocator& alloc = Allocator())
: m_(comp, alloc)
{
// This is linear if [first, last) is already sorted (and if we
// can figure out the distance between the two iterators).
insert(first, last);
}
explicit sorted_vector_set(
std::initializer_list<value_type> list,
const Compare& comp = Compare(),
const Allocator& alloc = Allocator())
: m_(comp, alloc)
{
insert(list.begin(), list.end());
}
key_compare key_comp() const { return m_; }
value_compare value_comp() const { return m_; }
iterator begin() { return m_.cont_.begin(); }
iterator end() { return m_.cont_.end(); }
const_iterator begin() const { return m_.cont_.begin(); }
const_iterator end() const { return m_.cont_.end(); }
reverse_iterator rbegin() { return m_.cont_.rbegin(); }
reverse_iterator rend() { return m_.cont_.rend(); }
const_reverse_iterator rbegin() const { return m_.cont_.rbegin(); }
const_reverse_iterator rend() const { return m_.cont_.rend(); }
void clear() { return m_.cont_.clear(); }
size_type size() const { return m_.cont_.size(); }
size_type max_size() const { return m_.cont_.max_size(); }
bool empty() const { return m_.cont_.empty(); }
void reserve(size_type s) { return m_.cont_.reserve(s); }
void shrink_to_fit() { m_.cont_.shrink_to_fit(); }
size_type capacity() const { return m_.cont_.capacity(); }
std::pair<iterator,bool> insert(const value_type& value) {
return insert(value_type(value));
}
std::pair<iterator,bool> insert(value_type&& value) {
iterator it = lower_bound(value);
if (it == end() || value_comp()(value, *it)) {
it = get_growth_policy().increase_capacity(m_.cont_, it);
return std::make_pair(m_.cont_.insert(it, std::move(value)), true);
}
return std::make_pair(it, false);
}
iterator insert(iterator hint, const value_type& value) {
return insert(hint, value_type(value));
}
iterator insert(iterator hint, value_type&& value) {
return detail::insert_with_hint(*this, m_.cont_, hint, std::move(value),
get_growth_policy());
}
到这里,最让我头疼的就是插入的判断条件。