std::unordered_map и структура с двумя полями
От: B0FEE664  
Дата: 26.02.25 14:11
Оценка:
Можно ли используя structured bindings написать шаблонную универсальную хэш-функцию для std::unordered_map при условияя, что для каждого из полей структуры есть (стандартная) хэш функция?
И каждый день — без права на ошибку...
Re: std::unordered_map и структура с двумя полями
От: Chorkov Россия  
Дата: 26.02.25 15:36
Оценка: 1 (1)
Здравствуйте, B0FEE664, Вы писали:

BFE>Можно ли используя structured bindings написать шаблонную универсальную хэш-функцию для std::unordered_map при условияя, что для каждого из полей структуры есть (стандартная) хэш функция?


Можно.
Стандартной нет.
Есть boost::pfr::hash

https://www.boost.org/doc/libs/1_87_0/doc/html/reference_section_of_pfr.html#doxygen.reference_section_of_pfr.functors_8hpp
https://www.boost.org/doc/libs/1_87_0/doc/html/doxygen/reference_section_of_pfr/structboost_1_1pfr_1_1hash.html

#include <boost/pfr/functors.hpp>
struct my_struct {      // No operators defined for that structure
    int i; short s; char data[7]; bool bl; int a,b,c,d,e,f;
};
// ...

std::unordered_set<
    my_struct,
    boost::pfr::hash<my_struct>,
    boost::pfr::equal_to<my_struct>
> my_set;
Отредактировано 26.02.2025 15:56 Chorkov . Предыдущая версия . Еще …
Отредактировано 26.02.2025 15:53 Chorkov . Предыдущая версия .
Re[2]: std::unordered_map и структура с двумя полями
От: B0FEE664  
Дата: 26.02.25 19:19
Оценка: +1
Здравствуйте, Chorkov, Вы писали:

BFE>>Можно ли используя structured bindings написать шаблонную универсальную хэш-функцию для std::unordered_map при условияя, что для каждого из полей структуры есть (стандартная) хэш функция?

C>Можно.
C>Стандартной нет.
C>Есть boost::pfr::hash

C>https://www.boost.org/doc/libs/1_87_0/doc/html/reference_section_of_pfr.html#doxygen.reference_section_of_pfr.functors_8hpp

C>https://www.boost.org/doc/libs/1_87_0/doc/html/doxygen/reference_section_of_pfr/structboost_1_1pfr_1_1hash.html

Какая-то очень сложная реализация: я так и не понял как они получают tuple с ссылками на поля...

Думаю можно по-простому, написал вот такой код:
template<typename TStruct>
struct St2Hash
{
    std::size_t operator()(const TStruct& k) const
    {
        const auto& [m1, m2] = k;
        return std::hash<typename std::remove_cv<decltype(m1)>::type>()(m1) ^ (std::hash<typename std::remove_cv<decltype(m2)>::type>()(m2) << 1);
    }
};
И каждый день — без права на ошибку...
Re[3]: std::unordered_map и структура с двумя полями
От: andrey.desman  
Дата: 26.02.25 19:27
Оценка: -1 :)
Здравствуйте, B0FEE664, Вы писали:

BFE>Какая-то очень сложная реализация: я так и не понял как они получают tuple с ссылками на поля...


Бинарным поиском до некоего N в компайл тайме находят количество полей, ну а дальше обычные structured bindings.

BFE>Думаю можно по-простому, написал вот такой код:


Если всегда 2 поля, то да.
Re[3]: std::unordered_map и структура с двумя полями
От: Великий Мессия google
Дата: 26.02.25 19:36
Оценка:
даже шмыга разобрался
https://rsdn.org/forum/cpp/8816359
Автор: Shmj
Дата: 15.09.24
Re[4]: std::unordered_map и структура с двумя полями
От: rg45 СССР  
Дата: 26.02.25 20:20
Оценка:
Здравствуйте, andrey.desman, Вы писали:

AD>Бинарным поиском до некоего N в компайл тайме находят количество полей, ну а дальше обычные structured bindings.


В качестве некоего N берется sizeof всей структуры. Это дает оценку сверху максимально возможного числа полей. А дальше идут декрементом. Бинарный поиск не катит, ибо агрегатная инициализация допускает меньшее количество элементов в инициализаторе, чем число полей в структуре.

P.S. Я после этого
Автор: rg45
Дата: 30.06.24
облома испробовал подход, предложенный Полухиным. Всё получилось, в принципе, но я не добился никаких преимуществ перед pfr, поэтому забил.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 26.02.2025 20:33 rg45 . Предыдущая версия .
Re[5]: std::unordered_map и структура с двумя полями
От: andrey.desman  
Дата: 26.02.25 20:38
Оценка: +1 -1 :)
Здравствуйте, rg45, Вы писали:

R>В качестве некоего N берется sizeof всей структуры. Это дает оценку сверху максимально возможного числа полей. А дальше идут декрементом. Бинарный поиск не катит, ибо агрегатная инициализация допускает меньшее количество элементов в инициализаторе, чем число полей в структуре.


Всего-то надо найти первое количество полей, которыми уже нельзя проинициализировать.

https://github.com/boostorg/pfr/blob/develop/include/boost/pfr/detail/fields_count.hpp#L230
Re[3]: std::unordered_map и структура с двумя полями
От: rg45 СССР  
Дата: 26.02.25 20:45
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Какая-то очень сложная реализация: я так и не понял как они получают tuple с ссылками на поля...


Я вот тут игрался на эту тему, может, тебе тоже будет интересно: http://coliru.stacked-crooked.com/a/22100a49d9fb2151

P.S. Да и кортежи с сылками на поля видятся мне некоторым овердизайном. При нормальных обобщённых подходах к программированию достаточно просто иметь возможность интерпретировать произвольную структуру как tuple-like тип.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.02.2025 7:48 rg45 . Предыдущая версия . Еще …
Отредактировано 27.02.2025 7:34 rg45 . Предыдущая версия .
Re[4]: std::unordered_map и структура с двумя полями
От: B0FEE664  
Дата: 28.02.25 09:27
Оценка:
Здравствуйте, andrey.desman, Вы писали:

BFE>>Какая-то очень сложная реализация: я так и не понял как они получают tuple с ссылками на поля...

AD>Бинарным поиском до некоего N в компайл тайме находят количество полей, ну а дальше обычные structured bindings.

Я ожидал, что для начала будет вызвана функция
template <class T>
constexpr auto structure_to_tuple(const T& val)

вот она
а потом к результату будет применён подсчёт hash.
А в реальности какой-то сложный подсчёт одновременно с разбором...

BFE>>Думаю можно по-простому, написал вот такой код:

AD>Если всегда 2 поля, то да.
Этот код, кстати, похож на:
template <class T>
constexpr auto tie_as_tuple(T& val, size_t_<2>) noexcept {
  auto& [a,b] = const_cast<std::remove_cv_t<T>&>(val); // ====================> Boost.PFR: User-provided type is not a SimpleAggregate.
  return ::boost::pfr::detail::make_tuple_of_references(detail::workaround_cast<T, decltype(a)>(a),detail::workaround_cast<T, decltype(b)>(b));
}

здесь

И так вплоть до
template <class T>
constexpr auto tie_as_tuple(T& val, size_t_<200>) noexcept



(Судя по названию файлов) для C++20 такого кодогенерирования не нужно? Или для C++20 используется тот же core17_generated.hpp ?
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.