set_intersection для двух разных типов множеств - PullRequest
6 голосов
/ 24 августа 2011

Есть ли способ сделать 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());

К сожалению, я не могу заставить этот код работать. Я даже не уверен, возможно ли это, но из описания 1013 * set_intersection я знаю, что могу использовать два разных итератора.

Я пытался найти примеры кода, которые делают то, что я хочу, но не нашел? Может ли кто-нибудь представить мне пример рабочего кода для моей проблемы?

Обновление: ошибка:

ошибка: stl_function.h: 227: нет соответствия для оператора

Заранее спасибо!

Ответы [ 4 ]

4 голосов
/ 24 августа 2011

Это не будет работать, поскольку оба входа должны быть назначены типу выходного итератора.Вы можете добавить некоторые неявные операторы преобразования в X1, X2, которые конвертируют между ними, чтобы это работало.

3 голосов
/ 24 августа 2011

Комментарий 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 ());
}
2 голосов
/ 24 августа 2011

Я не думаю, что это возможно, как есть, (по крайней мере, без пользовательского преобразования). Из раздела «Требования к типам» в документации : InputIterator1 and InputIterator2 have the same value type.

0 голосов
/ 23 января 2018

Прежде всего, согласно документации set_intersection использует оператор <.И, во-вторых, вы можете создать третью структуру, которая будет извлекать из типа поля, которые вы будете использовать для сравнения </p>

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 :: Вариант) Я думаю, что это уже делает это ...

...