set_intersection для двух разных типов множеств
Есть ли способ сделать std::set_intersection для двух разных типов множеств?
У меня есть два комплекта:
std::set<X1> l_set1;
std::set<X2> l_set2;
Я могу определить для них какой-нибудь компаратор, который проверяет, равны ли X1 и X2.
struct sample_comparer
{
bool operator()(const &X1 p_left, const &X2 p_right)
{
return p_left == p_right;
}
};
Теперь я пытаюсь сделать пересечение наборов на этих двух наборах:
std::set<X1> l_intersect;
std::set_intersection(l_set1.begin(), l_set1.end(), l_set2.begin(), l_set2.end(),
std::inserter(l_intersect, l_intersect.begin()), sample_comparer());
К сожалению, я не могу заставить этот код работать. Я даже не уверен, возможно ли это, но из описания set_intersection я знаю, что могу использовать два разных итератора.
Я пытался найти примеры кода, которые делают то, что я хочу, но не нашел? Может ли кто-нибудь представить мне пример рабочего кода для моей проблемы?
Обновление: ошибка:
ошибка: stl_function.h:227: нет совпадения для 'operator<' в '__x <__y'
Заранее спасибо!
4 ответа
Комментарий PlasmaHH, вероятно, является проблемой.
Такие функции, как set_intersection, работают в первую очередь: a < b
а потом b < a
В результате ample_comparer должен уметь сравнивать оба способа:
struct sample_comparer
{
bool operator()(const &X1 p_left, const &X2 p_right)
{
return p_left == p_right;
}
bool operator()(const &X2 p_left, const &X1 p_right)
{
return p_left == p_right;
}
};
Следующее на самом деле не делает ничего разумного - но оно компилируется чисто:
struct A
{
struct Compare { bool operator () (A const &, A const &) { return false;} };
};
struct B
{
struct Compare { bool operator () (B const &, B const &) { return false; } };
};
typedef std::set<A, A::Compare> S1;
typedef std::set<B, B::Compare> S2;
class IntersectionCompare
{
public:
bool operator ()(S1::value_type, S2::value_type) { return false; }
bool operator ()(S2::value_type, S1::value_type) { return false; }
};
void bar (S1 & s1, S2 & s2)
{
S1 result;
std::set_intersection (s1.begin ()
, s1.end ()
, s2.begin ()
, s2.end ()
, std :: insert_iterator< S1 > (result, result.end ())
, IntersectionCompare ());
}
Это не будет работать, поскольку оба входа должны быть назначены типу выходного итератора. Вы можете добавить некоторые неявные операторы преобразования в X1, X2, которые конвертируют между ними, чтобы это работало.
Я не думаю, что это возможно, как есть, (по крайней мере, без пользовательского преобразования). Из раздела "Требования к типам" в документации: InputIterator1 and InputIterator2 have the same value type.
Прежде всего, согласно документации, set_intersection использует оператор<. Во-вторых, вы можете создать третью структуру, которая будет извлекать из типа поля, которые вы будете использовать для сравнения.
std::set<X1> l_set1;
std::set<X2> l_set2;
struct XCompare
{
int value;
XCompare(const X1& x)
{
value = x.value;
}
XCompare(const X2& x)
{
value = x.value;
}
}
std::set_intersection(...,...,[](const XCompare& c1, const XCompare& c2){
... } )
Вы можете пойти по этому пути и создать собственную обертку, которая может делать все, если ваши два типа не могут сравнить
template<typename T1, typename T2>
struct ValueWrapper
{
T1 const* v1 = nullptr;
T2 const* v2 = nullptr;
ValueWrapper(const T1& value)
{
v1 = &value;
}
ValueWrapper(const T2& value)
{
v2 = &value;
}
bool operator<(const ValueWrapper& other)
{
if (v1 != nullptr)
{
if (other.v1 != nullptr)
{
return *v1 < *(other.v2)
}
... } }
template<typename T1, typename T2>
struct ValueWrapperComparator
{
bool operator()(ValueWrapper<T1,T2> v1, ValueWrapper<T1,T2> v2)
{
return v1 < v2;
}
}
Что-то вроде того. Я не проверял это, и он не скомпилируется, но вы поняли. Может быть, что-то похожее скрыто что-то похожее где-то в библиотеках STL
Редактировать: Кстати, я думаю, что вы можете использовать какой-то тип варианта (Boost:: Вариант или STD:: Вариант) Я думаю, что это уже делает...