Можно ли использовать элементы другого типа, чем те, которые содержатся в 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
указатель (вместо использования контейнера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
в любом порядке.)
Немного предыстории проблемы, которую я пытаюсь решить, на всякий случай, если кто-нибудь может порекомендовать лучший подход: мне нужно упорядочить коллекцию по нескольким критериям, поэтому у меня есть несколькоMetadataThingy
контейнеры, все отсортировано по разным критериям. «Метаданные» в этом случае - это то, что мне нужно, чтобы отслеживать положение элементов во всех контейнерах, чтобы я мог быстро удалить их. Это звучит как идеальная работа для многоадресных контейнеров, но порядок этих элементов постоянно меняется, что, по мнению AFAIK, не сработает.