2010-12-01 5 views
2

J'ai regardé les constructeurs de unordered_set. Est-ce qu'il n'est pas possible de construire un unordered_set avec une instance d'allocateur personnalisée SANS définir le nombre de segments de hachage? Je préfère vraiment ne pas jouer avec les détails d'implémentation parce que je veux un allocateur personnalisé, et le type ne fournit aucune définition pour la valeur par défaut. MSDN donne seulement trois surcharges pour le constructeur, dont aucune n'est terriblement utile.std :: constructeurs unordered_set

Editer: Merde sacrée. Mon implémentation STL de std :: hash ne se spécialise pas pour les chaînes avec un type d'allocateur personnalisé - elle ne peut faire que les typedefs explicites std :: string et std :: wstring. Je veux dire, je peux comprendre ne pas vouloir essayer de hacher les chaînes de caractères aléatoires, mais juste parce qu'il a un allocateur personnalisé? Cela me dégoûte.

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

Résout les problèmes, mais les constructions redondantes et la copie? Ewwwww.

+0

En ce qui concerne votre édition: yup, j'ai peur. 'std :: hash 'fait un peu défaut, en particulier je pense que la norme devrait fournir une fonction pour hacher une séquence d'octets, pour la rendre plus facile à spécialiser pour les UDT (y compris votre chaîne avec l'allocateur personnalisé). Mais puisque votre chaîne alternativement allouée n'est pas liée à l'une des spécialisations obligatoires de 'hash', vous êtes SOOL sans aide en vue. Je pense que vous devez simplement choisir votre propre algorithme de hachage, puis écrire une spécialisation ou spécifier le hachage dans votre conteneur. –

+0

@Steve: Pas tout à fait. Les constructeurs basic_string peuvent prendre n'importe quel itérateur, donc il n'était pas vraiment difficile de l'étendre à l'agnostic allocator, mais cela implique une copie redondante, ce qui me fait RAEG. – Puppy

+0

@DeadMG: oui, selon la raison pour laquelle vous utilisez un allocateur personnalisé. Si vous voulez que * all * allocation dans votre programme passe par votre allocateur, alors ce n'est pas seulement une copie redondante, c'est l'échec total. –

Répondre

2

C'est étrange, mais vous avez raison. Je suppose que la pensée était qu'il est trop difficile de supporter toutes les combinaisons de paramètres possibles, avec des valeurs par défaut.

La meilleure façon que je peux penser à gérer est de construire un unordered_set vide avec tous les paramètres par défaut, obtenir le nombre de seau par défaut de l'aide unordered_set::bucket_count, et ensuite utiliser que comme entrée lorsque vous instancier le conteneur que vous voulez réellement.

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

Je ne peux pas faire cela si mon allocateur personnalisé ne peut pas être construit par défaut. – Puppy

+0

Pourquoi ne pas coder par mon travail d'édition? –

+0

@Steve: Parce que YourAllocator() est une erreur de compilation, car il n'y a pas de constructeur par défaut. – Puppy

0

Puisque vous écrivez le Allocator, il est logique de contrôler le nombre de seaux trop, après tout les deux sont liés la mémoire :)

Steve a donné au cœur de la méthode si vous ne voulez pas à, maintenant laissez-moi vous propose une fonction d'assistance :)

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

Et avec cela, une aide peu (simple):

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

fonctionne assez bien avec auto:

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

Vous pouvez aussi, bien sûr, il suffit de déchirer la constante de votre mise en œuvre préférée.

+0

Non, cela n'a pas de sens de contrôler les deux, car on contrôle combien de mémoire est allouée, ou non, et les détails d'implémentation de l'algorithme en question - et l'autre ne fait que le mesurer. Les deux ne sont pas forcément liés. – Puppy