#prog #cpp #python
Что общего у C++ и Python?
Правильно: что в C++, что в Python нельзя распаковывать кортежи в аргументах лямбды.
Что общего у C++ и Python?
Правильно: что в C++, что в Python нельзя распаковывать кортежи в аргументах лямбды.
Stack Overflow
Structured binding in lambda arguments
Why I cannot use C++17 structured binding in this case?
std::map<int, int> m;
std::find_if( m.cbegin(), m.cend(), []( const auto & [x, y] ){ return x == y; } );
std::map<int, int> m;
std::find_if( m.cbegin(), m.cend(), []( const auto & [x, y] ){ return x == y; } );
🌚11👌4
#prog #cpp
В стандартной библиотеке C++ есть unordered контейнеры, которые для проверки принадлежности элементов контейнеру используют хэш-функции (помимо равенства, разумеется). Для того, чтобы хэшировать значение, нужно знать, как это делается.
В C++ операции хеширования можно переопределять для конкретных контейнеров (это один из шаблонных параметров), но по умолчанию используется std::hash. Для того, чтобы определить операцию хеширования для своего типа, нужно написать специализацию
Пусть у нас вот такой простой тип:
Попробуем сделать его хешируемым:
И вот тут мы сталкиваемся с проблемой: при условии, что у нас все поля хэшируемые, как нам получить хэш от всех них? Увы, std тут вообще никак не помогает. Максимум, что могут предложить на просторах интернета — это использовать boost::hash_combine (это даже рекомендуют на cppreference.com). Мало того, что тащить буст ради этого не хочется, так ещё и комбинирование происходит на уровне готовых хэшей. Это фактически приводит к двойному хэшированию, что обычно на качестве хэш-функции сказывается не в лучшую сторону.
В теории можно было бы организовать разделение на саму хэш-функцию и на описание того, какие и в каком порядке поля типа хэшируются... То есть сделать так, как в Rust. И это даже предлагали сделать для C++ в предложении N3980 aka Types Don't Know #. И подано это предложение было... 24 мая 2014 года. То есть десять лет назад, да. А воз и ныне там.
В стандартной библиотеке C++ есть unordered контейнеры, которые для проверки принадлежности элементов контейнеру используют хэш-функции (помимо равенства, разумеется). Для того, чтобы хэшировать значение, нужно знать, как это делается.
В C++ операции хеширования можно переопределять для конкретных контейнеров (это один из шаблонных параметров), но по умолчанию используется std::hash. Для того, чтобы определить операцию хеширования для своего типа, нужно написать специализацию
std::hash для своего типа (обязательно в пространстве имён std) и написать свою реализацию operator(), которая будет принимать хэшируемый объект и возвращать std::size_t в качестве результата.Пусть у нас вот такой простой тип:
struct Point {
int x;
int y;
};Попробуем сделать его хешируемым:
#include <cstddef>
#include <functional>
template <> struct std::hash<Point> {
std::size_t operator()(const Point& p) {
// а как...
}
};
И вот тут мы сталкиваемся с проблемой: при условии, что у нас все поля хэшируемые, как нам получить хэш от всех них? Увы, std тут вообще никак не помогает. Максимум, что могут предложить на просторах интернета — это использовать boost::hash_combine (это даже рекомендуют на cppreference.com). Мало того, что тащить буст ради этого не хочется, так ещё и комбинирование происходит на уровне готовых хэшей. Это фактически приводит к двойному хэшированию, что обычно на качестве хэш-функции сказывается не в лучшую сторону.
В теории можно было бы организовать разделение на саму хэш-функцию и на описание того, какие и в каком порядке поля типа хэшируются... То есть сделать так, как в Rust. И это даже предлагали сделать для C++ в предложении N3980 aka Types Don't Know #. И подано это предложение было... 24 мая 2014 года. То есть десять лет назад, да. А воз и ныне там.
Arthur O’Dwyer
Why can’t I specialize std::hash inside my own namespace?
This question comes up a lot on the cpplang Slack.
Suppose I have a class named my::Book, and I want to put it into a std::unordered_set.
Then I need to write a std::hash specialization for it. So I write:
Suppose I have a class named my::Book, and I want to put it into a std::unordered_set.
Then I need to write a std::hash specialization for it. So I write:
🤡9🤷6🤔3🤣3