Domanda

Sono stato a guardare i costruttori di unordered_set. Non è possibile costruire un unordered_set con un'istanza allocatore personalizzato senza impostare il numero di bucket hash? Mi piacerebbe davvero meglio non pasticciare con dettagli di implementazione perché voglio un allocatore personalizzato, e il tipo non fornisce le definizioni per il valore di default. MSDN dà solo come tre sovraccarichi per il costruttore, nessuno dei quali è terribilmente utile.

Modifica: Holy crap. La mia implementazione STL di std :: hash non si specializzerà per le stringhe con un allocatore personalizzato del tipo che può fare solo le typedef espliciti std :: string e std :: wstring. Voglio dire, posso capire che non vogliono cercare di hash stringhe di caratteri casuali, ma solo perché ha un allocatore personalizzato? Questo mi fa schifo.

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()));
    }
};

risolve i problemi, ma le costruzioni ridondanti e la copia? Ewwwww.

È stato utile?

Soluzione

Questo è strano, ma hai ragione. Suppongo che il pensiero è stato che è eccessivo per supportare tutte le possibili combinazioni di parametri, con valori di default.

Il modo migliore che posso pensare a gestire questa situazione è di costruire un unordered_set vuoto con tutte le impostazioni predefinite, ottenere il conteggio secchio di default da utilizzando unordered_set::bucket_count, e quindi utilizzare tale come input quando si crea un'istanza del contenitore si vuole realmente.

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

Altri suggerimenti

Dal momento che si sta scrivendo il Allocator, ha senso per controllare il numero di secchi troppo, dopo tutto sono entrambi legati memoria:)

Steve ha dato il cuore del metodo se non si vuole, ora vorrei proporre una funzione di supporto:)

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

E con questo, un po '(semplice) helper:

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);
}

funziona abbastanza bene con auto:

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

Si potrebbe anche, naturalmente, semplicemente strappare la costante dalla vostra applicazione preferita.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top