问题描述
假设我有以下内容:
struct MetadataThingy {
void *actual_thingy;
int some_metadata;
int more_metadata;
bool operator<(MetadataThingy const& other) const {
return actual_thingy < other.actual_thingy;
}
};
其中actual_thingy
指向一些重要数据,我希望容器按actual_thingy
的值排序,而不是所指向的元素的值,但是我需要存储其他有关它的数据,因此我创建了包装器类MetadataThingy
具有一个比较器,该比较器仅考虑actual_thingy
指针的值(而不是使用void *
的容器)
where actual_thingy
points to some data of importance and I want the container ordered by the value of actual_thingy
rather than the value of the element pointed at, but I need to store some other data about it, so I created the wrapper class MetadataThingy
with a comparator that only considers the value of the actual_thingy
pointer (rather than using a container of void *
)
现在,给出以下代码:
std::set<MetadataThingy> thingy_set;
void test() {
MetadataThingy m1 { nullptr, 5, 20 };
MetadataThingy m2 { &m1, 1, 2 };
MetadataThingy m3 { &m2, 6, 0 };
thingy_set.insert(m1);
thingy_set.insert(m2);
thingy_set.insert(m3);
MetadataThingy m;
m = *thingy_set.find(m2); // OK.
m = *thingy_set.find(static_cast<void *>(&m2)); // Nope. Can't use a pointer.
}
由于每个MetadataThingy
可以由其存储的指针值唯一标识并由指针值排序,因此仅使用void *
作为键来查找/删除对象就很有意义.但是,按照目前的情况,每次搜索元素时,我都必须创建一个虚拟MetadataThingy
,这确实让人感到困惑.我已经考虑过只使用map
并将指针作为键,将MetadataThingy
作为值,但是由于每个MetadataThingy
都还必须包含指针,因此有点多余.因此,有一种方法可以使用存储在集合中的元素以外的其他类型的元素来查找或删除集合中的值,前提是两种类型的元素可以相互比较,并且一种类型可以唯一地映射到另一种类型(void *
和MetadataThingy
是同构的)? (我没有在上面的代码中包含任何内容,但假设有运算符重载可以按任意顺序比较void *
和MetadataThingy
.)
Since each MetadataThingy
can be uniquely identified by the pointer value it stores and is ordered by the pointer value, it would make sense to find/delete objects simply by using a void *
as the key. As it currently stands, though, I would have to create a dummy MetadataThingy
each time I search for an element, which feels really kludgy. I've already considered using just a map
with pointers as key and MetadataThingy
as value but since each MetadataThingy
must also contain the pointer anyway, this feels a bit redundant. So, is there a way to use an element of a type other than that stored in a set to find or delete values in the set, given that elements of the two types are mutually comparable and that elements of one type can be uniquely mapped into the other ( void *
and MetadataThingy
are isomorphic)? (I didn't include any in the above code, but suppose there are operator overloads for comparing void *
and MetadataThingy
in any order.)
我要解决的问题的一些背景知识,以防万一有人可以推荐一种更好的方法:我需要按多个条件订购一个集合,所以我有几个MetadataThingy
容器,所有容器均按不同的条件排序.在这种情况下,"Metadata"将是我需要跟踪所有容器中元素位置的东西,以便可以快速删除.对于增强型多索引容器来说,这听起来像是一项完美的工作,但是这些元素的顺序不断变化,而AFAIK则意味着它将无法工作.
A little background on the problem I'm trying to solve, just in case anyone can recommend a better approach: I need to order a collection by multiple criteria, so I have several MetadataThingy
containers, all sorted by different criteria. "Metadata" in this case would be stuff I need to track the positions of the elements in all containers so that I can do fast removal. This would sound like a perfect job for boost multi-index containers, but the ordering of these elements is constantly changing, which AFAIK would mean it won't work.
推荐答案
从C ++ 14开始,std::set
具有其查找函数find
,lower_bound
等的模板化版本.它们使您可以传递任何只要比较器支持,就可以进行比较.
As of C++14, std::set
has templated versions of its lookup functions find
, lower_bound
, etc. They allow you to pass any object for comparison, as long as the comparer supports it.
这意味着只要比较器支持比较MetadataThingy
和void*
,您就可以直接将void*
传递给find
.
This means you can directly pass your void*
to find
, as long as the comparer supports comparing MetadataThingy
and void*
.
有关更多信息,请参见 http://en.cppreference.com/w/cpp/container/set/find .
For more information, see http://en.cppreference.com/w/cpp/container/set/find.
要了解有关Compare::is_transparent
的限制,我发现此StackOverflow问题非常有用.
To understand the limitation regarding Compare::is_transparent
, I found this StackOverflow question very helpful.
这篇关于是否可以使用与std :: set中所包含类型不同的元素来执行搜索和删除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!