C bool std::operator < ошибка с отображением с ключом std::unordered_set<int,std::hash>

#c #unordered-set

#c #неупорядоченный набор

Вопрос:

когда я пытаюсь вставить в эту карту:

std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> >

Я получил эту ошибку

ошибка C2784: ‘bool std::operator <(const std::_Tree<_Traits> amp;,const std::_Tree<_Traits> amp;)’: не удалось вывести аргумент шаблона для ‘const std::_Tree<_Traits> amp;’ из ‘const std::unordered_set,std::equal_to<_Kty>,std::распределитель<_Kty>>’

Мои данные определяются следующим образом:

     struct Trans {
    int Item;
    float Prob;
    float W;
};
bool operator<(const Trans amp;a, const Trans amp;b)
    {
        return a.Item < b.Item;
    }
    bool operator==( Trans c,  Trans d) { return c.Item == d.Item; }


    struct MyHash {
        size_t operator()(const Transamp; x) const { return std::hash<int>()(x.Item);  }
    };


std::vector<std::vector<Trans>> data;
std::map<std::unordered_set<int>, float> S1;
std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> > S2;
std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> > S3;
  

Часть, в которой проблема:

     do
        {

std::unordered_set<Trans, MyHash> KS(data[i].begin(), data[i].begin()   k);
std::unordered_set<int > elem;

float esupp = 1;
float Weight = 0;
float Wesupp = 1;
    for (auto const amp;iter : KS)
        {
          elem.insert(iter.Item);
           esupp *= iter.Prob;
          Weight  = iter.W;
        }
        Weight = Weight / k;


        /*
        some code, and until here I didn't get any problem
        */

            **// This the area that has the problem** 

    S1[elem] = std::move(S1[elem]   esupp);
    Wesupp = Weight * S1[elem];
    S2[elem].first = std::move(S2[elem].first   esupp);
    S2[elem].second = std::make_pair(elem, Wesupp);
  } while (next_combination(data[i].begin(), data[i].begin()   k, data[i].end()));
  

Комментарии:

1. Какая фактическая строка содержит ошибку?

2. Помимо всего прочего, эта строка выглядит неправильно: S2[elem].second = std::make_pair(elem, Wesupp);

3. Я бы серьезно пересмотрел дизайн структуры данных… unordered_set как ключи? std::pair<float, std::pair<float, float>> ? (по крайней мере, используйте std::tuple или std::array<float, 3> )

4. @ben каждую строку из ` S1 [elem] = std::move(S1[elem] esupp)` в ` S2[elem].second = std::make_pair(elem, Wesupp);` вызывает ошибку

5.@marco-a в контейнер S2 я хотел бы вставить unordered_set elem с его тремя значениями с плавающей запятой. каждый раунд в цикле elem имеет unordered_set , если он похож на предыдущий, я обновлю их три значения с плавающей запятой, в противном случае я вставлю new unordered_set с его тремя значениями с плавающей запятой.

Ответ №1:

A std::map ожидает, что его ключ реализует оператор < , если не указан компаратор.

Ваш тип ключа std::unordered_set не реализует «меньше».

Как упоминает @T.C., вы могли бы использовать std::set вместо std::unordered_set .

Комментарии:

1. спасибо, но если я заменю на std::map , std::unordered_map я получу другую ошибку, error C2338: The C Standard doesn't provide a hash for this type.

2. @Sandy Тогда я удалю это предложение. Причина вашей ошибки остается той же. C этого не поддерживает.

3. std::set действительно operator <() определен стандартом.

4. Спасибо вам всем, мне нужно использовать std::unordered_set не std::set потому, что я использовал хеш-функцию для проверки KS наличия супернабора любого из предыдущего набора, который хранится в S2', I have file of 100k lines, each line has different size, and I used next_combination`для генерации KS , и я использовал хеширование для части сравнений, чтобы сократить время вместо использования STL includes()

5. @Sandy Ты действительно измерял скорость с std::set помощью / std::includes ? Когда речь идет о производительности, всегда измеряйте.

Ответ №2:

Ваша текущая ошибка, как указал Дрю Дорманн, вызвана std::unordered_set отсутствием an operator < .

std::set однако он перегружен operator < , поэтому вы можете его использовать.

Однако проблема с вашим кодом глубже, чем это. Например:

 S1[elem] = std::move(S1[elem]   esupp);
  

Вы присваиваете float . Нет абсолютно никакого смысла в использовании std::move , тем более, S1[elem] esupp что это уже rvalue . Обычный способ написания этой строки будет S1[elem] = esupp;

 S2[elem].first = std::move(S2[elem].first   esupp);
  

Та же проблема.

 S2[elem].second = std::make_pair(elem, Wesupp);
  

LHS присваивания равно a std::pair<float, float> ; RHS создает a std::pair<std::unordered_set<int>, float> .

И, как я упоминал в комментариях, std::pair<float, std::pair<float, float>> это просто плохой дизайн. Это должна быть, по крайней мере std::tuple , или даже лучше std::array<float, 3> , или даже лучше простая структура, которая проясняет, что на самом деле означает каждый из трех поплавков.

Кроме того, использование a set<int> (неупорядоченного или нет) в качестве ключа в map — довольно странный дизайн. Вы хотите просто поддерживать список set<int> -3x float пар, которые вы можете перебирать, или вы действительно хотите иметь возможность эффективно индексировать с помощью a set<int> ? Если вам не нужна эффективная индексация, просто используйте вектор пар, а не карту.

Комментарии:

1. Английский не мой родной язык, поэтому я использовал пример для описания S2, хотелось бы, чтобы у вас было время взглянуть на него. im67.gulfup.com/REB8Fj.png