Слово.
У меня есть структура, содержащая одно поле, которое я хотел бы установить для сравнения и эквивалентности, и другие поля в качестве метаданных:
struct read_tag{
unsigned int read_id; // want std::set to use this
int offset; // metadata
bool orientation; // metadata
};
У меня есть функтор, чтобы сделать работу:
struct read_tag_compare {
bool operator() (const read_tag &a, const read_tag &b) const {
return a.read_id > b.read_id
}
};
и декл. необходимый набор как
std::set<read_tag, read_tag_compare> block;
Пока что все компилируется. Проблема ниже:
Как мне сделать набор, содержащий std::set<read_tag, read_tag_compare>
, Я хочу что-то вроде этого:
std::set< std::set<read_tag, read_tag_compare> > blocks;
blocks.insert(a_block); // comp error
Но это дает мне очень большую и трудную для расшифровки ошибку.
Я думал, что это будет рекурсивно проверять, как сравниваются внутренние наборы, и распространять это на внешние наборы. Все, что нужно было сделать, это определить компаратор для самого внутреннего набора.
Например
std::set<std:set<unsigned int>> set_o_sets;
работает нормально, без меня, чтобы определить, как сравнивать std::set<unsigned int>
Любая помощь приветствуется: D
<
Сравнение по std::set
использования std::lexicographical_compare
без компаратора, то есть он просто пересылает <
на тип элемента. (Это ограничение стандартной библиотеки, поскольку она определена для всех контейнеров, а не только для упорядоченно-ассоциативных.) Итак, вам нужен собственный компаратор для наборов наборов, который использует корректную перегрузку лексикографического сравнения:
using read_tag_set = std::set<read_tag, read_tag_compare>;
struct read_tag_set_compare {
bool operator()(const read_tag_set &a, const read_tag_set &b) const noexcept {
return std::lexicographical_compare(a.begin(), a.end(),
b.begin(), b.end(), a.key_comp());
// ^^^^^^^^^^^^
}
};
Теперь используйте: std::set<read_tag_set, read_tag_set_compare>
Код показывает, почему не существует очевидного «исправления» к упорядоченным ассоциативным контейнерам, которое могло бы сделать это «просто работающим»: если контейнеры используют пользовательские предикаты с сохранением состояния, то в общем случае не гарантируется, что члены двух отдельных контейнеров могут на самом деле сравнивать друг с другом вообще. Все, что вы знаете, это то, что элементы в один контейнер сопоставим с компаратором этого контейнера. Поэтому, когда вы используете собственный компаратор, вам лучше также четко указать, как соотносятся два разных контейнера, и вы явно утверждаете, что имеет смысл сравнивать два контейнера.
Он скомпилирован без ошибок с моей g ++ — 5.3.1 Ubuntu ..
#include<set>
#include<iostream>
using namespace std;
struct read_tag{
unsigned int read_id; // want std::set to use this
int offset; // metadata
bool orientation; // metadata
};
struct read_tag_compare {
bool operator() (const read_tag &a, const read_tag &b) const {
return a.read_id > b.read_id;
}
};
struct read_compare {
bool operator() (const set<read_tag, read_tag_compare> &a, const set<read_tag, read_tag_compare> &b) const {
return true;
}
};
int main()
{
set<read_tag, read_tag_compare> block;
set<set<read_tag, read_tag_compare>, read_compare> blocks;
blocks.insert(block)
}
Выше было то, что я составил.