是否可以使用与std :: set中包含的不同类型的元素来执行搜索和删除?

jay*_*ica 5 c++ set stdset

假设我有以下内容:

struct MetadataThingy {

    void *actual_thingy;
    int some_metadata;
    int more_metadata;

    bool operator<(MetadataThingy const& other) const {
        return actual_thingy < other.actual_thingy;
    }

};
Run Code Online (Sandbox Code Playgroud)

其中actual_thingy指向一些重要数据,我希望容器按值actual_thingy而不是指向的元素的值排序,但是我需要存储一些关于它的其他数据,所以我MetadataThingy用一个只考虑的比较器创建了包装类actual_thingy指针的值(而不是使用容器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.

}
Run Code Online (Sandbox Code Playgroud)

由于每个MetadataThingy都可以由它存储的指针值唯一地标识并且由指针值排序,因此仅使用a void *作为键来查找/删除对象是有意义的.但是,就目前的情况而言,MetadataThingy每次我搜索一个元素时,我都必须创建一个虚拟元素.我已经考虑过只map使用指针作为键和MetadataThingy值,但由于每个都MetadataThingy必须包含指针,所以这感觉有点多余.那么,是否有一种方法可以使用除了存储在集合中的类型之外的类型的元素来查找或删除集合中的值,因为这两种类型的元素可以相互比较,并且一种类型的元素可以唯一地映射到另一个(void *MetadataThingy是同构的)?(我在上面的代码中没有包含任何内容,但是假设有运算符重载用于比较void *MetadataThingy任何顺序.)

关于我试图解决的问题的一点背景,以防万一有人可以推荐一个更好的方法:我需要按多个标准订购一个集合,所以我有几个MetadataThingy容器,所有容器都按不同的标准排序.在这种情况下,"元数据"将是我需要跟踪所有容器中元素位置的东西,以便我可以快速删除.对于提升多索引容器来说,这听起来是一个完美的工作,但这些元素的排序不断变化,AFAIK意味着它不起作用.

Dan*_*olf 4

从 C++14 开始,std::set有其查找函数的模板化版本findlower_bound等等。它们允许您传递任何对象进行比较,只要比较器支持它。

这意味着只要比较器支持比较and ,您就可以直接传递void*to 。findMetadataThingyvoid*

有关更多信息,请参阅http://en.cppreference.com/w/cpp/container/set/find

为了理解有关的限制Compare::is_transparent,我发现这个 StackOverflow 问题非常有帮助。