我正在尝试实现或从概念上设计一个容器,该容器具有连续的内存但元素顺序不重要(并且被用于插入/删除对象)。
这与std::vector
类似,但解除了一个约束,即当一个元素被移除时,其他元素的相对顺序将被保留,因为在这种情况下,最后一个元素可以代替删除了一个。
我或多或少知道如何实现它(基于std::vector
和一些特殊的反向引用iterator
)但是我正在寻找一个参考实现来避免重新发明轮
我熟悉Boost.Container,但我找不到这样的容器。
boost::container::flat_set
很接近,但它保持顺序,这是不必要的。从某种意义上说,我正在寻找某种“boost::container::unordered_flat_set
”或“unordered_vector
”。
这是我期望的行为:
unordered_flat_set<T> ufs(100); // allocates 100 elements
ufs.reserve(120);
unordered_flat_set<T>::iterator it = ...; // find something
ufs.erase(it); // overwrite last element to that position, destroy last element
ufs.insert(T{}); //add element at "end", only if necessary reallocate, keep buffer memory in multiples of 2 (or 1.6). Element order is not fundamental, can be altered completely by a call to "erase".
ufs.size(); // report size
erase
和insert
都是O(1),(除非需要重新分配)。
这是一个尚未在标准或非标准容器中的概念。
(也许是无序的概念与当前的容器不能很好地配合。
毕竟唯一的“无序”目前是std::unordered_set
并且它是相当新的。)
这是一个参考(非常小)的实现,它主要是给出我正在寻找的概念的具体实现。事实上,我正在寻找是否已经存在将其应用于现有基本代码的概念。 我不是想重新发明轮子。
#include<iostream>
#include<vector>
template<class T>
class unordered_vector{
std::vector<T> impl_;
public:
unordered_vector(){}
void reserve(int i){impl_.reserve(i);}
struct iterator{
std::vector<T>* back_ptr;
int i;
T& operator*(){return back_ptr->operator[](i);}
iterator operator++(){++i; return *this;}
iterator operator--(){--i; return *this;}
bool operator==(iterator const& other) const{return back_ptr == other.back_ptr and i == other.i;}
bool operator!=(iterator const& other) const{return not(*this == other);}
};
int size(){return impl_.size();}
iterator erase(iterator it){
*it = it.back_ptr->last(); // should I use placement new here to not rely in customized (or not assignable object type)?
return it.back_ptr->erase(it.rbegin()); // I return this for compatibility, although there is no use for this
}
iterator insert(T t){
impl_.push_back(t); return {&impl_, size()-1};
}
iterator begin(){return {&impl_, 0};} // does an unordered container have a begin ?? ok, for compatibility, like std::unordered_set
iterator end(){return {&impl_, (int)impl_.size()};} // same question,
T& operator[](int i){return impl_[i];} // same question, if it is unordered v[i] has not a "salient" meaning.
};
int main(){
unordered_vector<double> uv;
uv.reserve(10);
uv.insert(1.1);
uv.insert(2.3);
uv.insert(5.4);
uv.insert(3.1);
std::cout << uv.size() << std::endl;
auto it = uv.begin();
assert( uv.begin() != uv.end());
assert( it != uv.end() );
for(auto it = uv.begin(); it != uv.end(); ++it){
std::cout << *it << std::endl;
}
}