是否可以使用与 std::set 中包含的不同类型的元素来执行搜索和删除?
假设我有以下内容:
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
指针的值的比较器(而不是使用 的容器无效 *
)
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
容器,都按不同的标准排序.在这种情况下,元数据"是我需要跟踪所有容器中元素位置的东西,以便我可以快速删除.这听起来像是提升多索引容器的完美工作,但这些元素的顺序不断变化,这意味着 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.
这意味着您可以直接将您的 void*
传递给 find
,只要比较器支持比较 MetadataThingy
和 void*
.
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
的限制,我发现 this StackOverflow问题很有帮助.
To understand the limitation regarding Compare::is_transparent
, I found this StackOverflow question very helpful.
相关文章