Pourquoi est-allocateur::relier nécessaire lorsque nous avons modèle des paramètres de modèle?

Chaque allocateur de classe doit avoir une interface semblable à la suivante:

template<class T>
class allocator
{
    ...
    template<class Other>
    struct rebind { typedef allocator<Other> other; };
};

Et les classes utilisation allocateurs de faire quelque chose de redondant comme ceci:

template<class T, class Alloc = std::allocator<T> >
class vector { ... };

Mais pourquoi est-ce nécessaire?

En d'autres termes, ne pouvait pas, ils ont juste dit:

template<class T>
class allocator { ... };

template<class T, template<class> class Alloc = std::allocator>
class vector { ... };

qui est à la fois plus élégant, moins redondant, et (dans certaines situations), potentiellement plus sûr?

Pourquoi ont-elles fait de la rebind route, ce qui provoque aussi davantage de redondance (c'est à dire que vous avez à dire T deux fois)?

(Question similaire va à char_traits et le reste... bien qu'ils n'ont pas tous des rebind, ils pourraient encore bénéficier de modèle de paramètres de modèle.)


Edit:

Mais cela ne fonctionnera pas si vous avez besoin de plus de 1 paramètre de modèle!

En fait, il fonctionne très bien!

template<unsigned int PoolSize>
struct pool
{
    template<class T>
    struct allocator
    {
        T pool[PoolSize];

        ...
    };
};

Maintenant, si vector a été définie de cette manière:

template<class T, template<class> class Alloc>
class vector { ... };

Ensuite, vous pouvez simplement dire:

typedef vector<int, pool<1>::allocator> int_vector;

Et il fonctionne parfaitement bien, sans avoir besoin de vous pour (redondance) dire int deux fois.

Et un rebind fonctionnement à l'intérieur vector serait juste de devenir Alloc<Other> au lieu de Alloc::template rebind<Other>::other.

  • Notez qu'en C++11, la condition est détendu et std::allocator_traits<SomeAllocator<T, Args...>>::rebind_alloc<U> est SomeAllocator<U, Args...> en tant que par défaut si SomeAllocator ne fournit pas rebind.
  • Pour le dernier point dans l'édition: la laideur de reliaison opération regarde à l'intérieur le vecteur de la mise en œuvre n'est pas pertinent. Vous, le maître d'œuvre, ont la charge de faire des choses facile pour l'utilisateur, même si cela signifie très laid et alambiqué code sous le capot. Si vous pouvez enterrer la laideur dans la mise en œuvre de laisser une interface épurée, il est de votre devoir de le faire.
  • Bien sûr, mais il est encore plus facile pour l'utilisateur? (De quelle façon? Exemples/les comparaisons seraient utiles! :D)
  • Euh, vous spécialiser... template<class> class my_special_allocator; template<> class my_special_allocator<my_type> { ... }; et puis la passer dans my_special_allocator. Étant donné que rebindmise en œuvre, aurait probablement besoin d'un modèle de toute façon, vous devez éviter ce dans l'ordre pour être un problème. Mais si vous êtes en insistant sur la non-utilisation de modèles à tous, eh bien, alors vous êtes à côté de l'essentiel... le "T" dans la STL est là pour une raison! Et autant que je sache, ce genre d'utilisation est le point de l'ensemble du modèle, les paramètres de modèle, en premier lieu... droit?
  • La vérité peut être décevant. Le modèle de reliaison idiome vient peut-être été plus facile à mettre en œuvre avec les anciens compilateurs. J'ai trouvé modèle argument de modèle de passer uniquement dans les nouveaux code STL. Il n'est donc pas que les réalisateurs tout simplement pas comme modèle arguments de modèle en général. Ce que j'aime personnellement modèle arguments de modèle est que l'intention spécifique est déjà visible au niveau de l'interface après l'analyse syntaxique, c'est à dire passer d'un type de stratégie interne de privé un usage générique.
  • Et si pool<1>::allocator<char>::rebind<int>::other doivent être pool<4>::allocator<int>.

InformationsquelleAutor Mehrdad | 2012-09-11