Вопрос

Я просматривал конструкторы unordered_set .Разве невозможно создать unordered_set с помощью пользовательского экземпляра распределителя БЕЗ установки количества хэш-сегментов?Я бы действительно предпочел не связываться с деталями реализации, потому что мне нужен пользовательский распределитель, а тип не предоставляет определений для значения по умолчанию.MSDN предоставляет только около трех перегрузок для конструктора, ни одна из которых не является ужасно полезной.

Редактировать:Святое дерьмо.Моя реализация STL std::hash не будет специализироваться на строках с пользовательским типом распределителя - она может выполнять только явные определения типов std::string и std:: wstring.Я имею в виду, я могу понять нежелание пытаться хэшировать случайные символьные строки, но только потому, что у него есть пользовательский распределитель?Это вызывает у меня отвращение.

tokens(std::unordered_set<string>().bucket_count(), std::hash<string>(), std::equal_to<string>(), stl_wrapper::hash_set<string>::allocator_type(this))
template<typename Char, typename CharTraits, typename Allocator> class std::hash<std::basic_string<Char, CharTraits, Allocator>>
    : public std::unary_function<std::basic_string<Char, CharTraits, Allocator>, std::size_t> {
public:
    size_t operator()(const std::basic_string<Char, CharTraits, Allocator>& ref) const {
        return std::hash<std::basic_string<Char, CharTraits>>()(std::basic_string<Char, CharTraits>(ref.begin(), ref.end()));
    }
};

Решает проблемы, но избыточные конструкции и копирование?Фу-у-у.

Это было полезно?

Решение

Это странно, но вы правы.Я предполагаю, что мысль заключалась в том, что поддерживать все возможные комбинации параметров по умолчанию - это перебор.

Лучший способ, который я могу придумать, чтобы справиться с этим, - это создать пустой unordered_set используя все настройки по умолчанию, получите из него количество корзин по умолчанию, используя unordered_set::bucket_count, а затем используйте это в качестве входных данных при создании экземпляра контейнера, который вам действительно нужен.

unordered_set<int> temp;
size_t buckets = temp.bucket_count;
unordered_set<string> actual(buckets, Hash(), Pred(), 
    YourAllocator(param1 /*, etc */));

Другие советы

Поскольку вы пишете Allocator, также имеет смысл контролировать количество сегментов, в конце концов, оба связаны с памятью :)

Стив изложил суть метода, если вы не хотите, теперь позвольте мне предложить вспомогательную функцию :)

template <typename T>
size_t number_buckets()
{
  std::unordered_set<T> useless;
  return useless.bucket_count();
}

И вместе с этим маленький (простой) помощник:

template <typename T, typename Hash, typename Pred, typename Allocator>
std::unordered_set<T,Hash,Pred,Allocator>
  make_unordered_set(Hash const& hash, Pred const& pred, Allocator const& alloc)
{
  static size_t const nbBuckets = number_buckets<T>();
  return std::unordered_set<T,Hash,Pred,Allocator>(nbBuckets, hash, pred, alloc);
}

Довольно хорошо работает с auto:

auto set = make_unordered_set<std::string>(Hash(), Pred(), Allocator(1,2,3));

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top