我正在寻找一个C ++容器来存储指向对象的指针,这些指针也符合以下要求。
std::set
不合适)std::array::size()
始终返回固定大小,std::array
不合适)operator []
。这是我的代码片段,我想删除用于检查元素大小和唯一性的断言。
#include <vector>
#include <set>
#include "assert.h"
class Foo {
public:
void DoSomething() {
}
};
int main() {
// a variable used to check whether a container is properly assigned
const uint8_t size_ = 2;
Foo foo1;
Foo foo2;
// Needs a kind of sequential containers to keep the order
// used std::vector instead of std::array to use member function size()
const std::vector<Foo*> vec = {
&foo1,
&foo2
};
std::set<Foo*> set_(vec.begin(), vec.end());
assert(vec.size() == size_); // size checking against pre-defined value
assert(vec.size() == set_.size()); // check for elements uniqueness
// Needs to access elements using [] operator
for (auto i = 0; i < size_; i++) {
vec[i]->DoSomething();
}
return 0;
}
是否有一个C ++容器,不需要在我的代码片段中使用两个断言?或者我应该创建自己的类来封装一个STL容器吗?
答案 0 :(得分:0)
这样一个类似于向量的类,除非你插入,它拒绝像集合或映射这样的重复项。
一个选项可能是Boost.Bimap,索引为T *和sequence_index。 你的矢量索引将通过sequence_index。在删除元素后,您甚至可能愿意接受序列中的漏洞。
坚持使用STLyou可以使用2个地图实现双向地图,或者下面使用地图和矢量:
请注意,通过继承vector,我可以免费获得所有的矢量方法,但我也冒险将用户向下转换为矢量。
没有使用包装器(la queue vs list)进行重新构造的一种方法是使其成为受保护的继承,然后显式地将所有方法重新公开。这实际上更安全,因为它可以确保您不会无意中留下一些矢量修改方法,这会使两个容器失去一步。
另请注意,如果您希望过滤掉任何重复项,则需要滚动自己的initializer_list构造函数。而且你必须做一些工作才能使这个线程安全。
template <class T>
class uniqvec : public std::vector<T*>
{
private:
typedef typename std::vector<T*> Base;
enum {push_back, pop_back, emplace_back, emplace}; //add anything else you don't like from vector
std::map <T*, size_t> uniquifier;
public:
std::pair<typename Base::iterator, bool> insert(T* t)
{
auto rv1 = uniquifier.insert(std::make_pair(t, Base::size()));
if (rv1.second)
{
Base::push_back(t);
}
return std::make_pair(Base::begin()+rv1.first.second, rv1.second);
}
void erase(T* t)
{
auto found = uniquifier.find(t);
if (found != uniquifier.end())
{
auto index = found->second;
uniquifier.erase(found);
Base::erase(Base::begin()+index);
for (auto& u : uniquifier)
if (u.second > index)
u.second--;
}
}
// Note that c++11 returns the next safe iterator,
// but I don't know if that should be in vector order or set order.
void erase(typename Base::iterator i)
{
return erase(*i);
}
};
答案 1 :(得分:0)
正如其他人所提到的那样,你的特定问题似乎就像XY问题一样(关于特定解决方案的杂草,而不是关注原始问题)。几年前提供了一个非常有用的流程图(归功于@MikaelPersson),它将帮助您选择最适合您需求的特定STL容器。您可以在In which scenario do I use a particular STL container?找到原始问题。