36 votes

Pourquoi ne std::stack pas utiliser de modèle de modèle de paramètre?

Pourquoi dois - std::stack et std::queue type d'utilisation paramètre de modèle à la place du modèle, le paramètre de modèle pour leurs sous-jacent type de conteneur?

c'est à dire pourquoi est - stack déclaré comme ceci:

template<typename T, typename Container = deque<T>>
class stack;

mais pas à ce point:

template<typename T, template<typename> class Container = deque>
class stack;

?

38voto

rubenvb Points 27271

Parce que en général, les conteneurs comme std::vector ont plus d'un argument de modèle. Par ne pas se soucier à ce sujet étant un modèle, vous permettre tout type de conteneur à être utilisé.

Comment

template<class T, class Allocator = std::allocator<T>> class vector;

ajustement sur

template<typename> class Container

comme vous l'avez dans votre stack? (Indice: il n'est pas!) Vous auriez besoin des cas particuliers pour chaque nombre et le type des arguments de modèle (type vs non-type) que vous souhaitez les soutenir, ce qui est stupide, parce que celles-ci ne contribuent pas plus d'informations qu'un simple

typename Container

Notez que pour obtenir les arguments de modèle, par exemple, l' std::vector, vous avez les typedefs std::vector::value_type et std::vector::allocator_type, la suppression de la nécessité d'avoir ces types de disponibles explicitement lorsque vous utilisez le type (c'est à dire l' Container de stack).

19voto

Holt Points 6689

En bref: Parce que l'utilisation d'un modèle de paramètre du modèle est plus restrictive* que l'utilisation d'un paramètre de type sans fournir d'avantages.

* Par "restrictif", je veux dire que vous devrez peut-être des trucs plus complexe à obtenir les mêmes résultats qu'avec un "simple" paramètre de type.

Pourquoi il n'y a pas d'avantages?

Votre std::stack a probablement un attribut comme ceci:

template <typename T, typename Container>
struct stack {
    Container container;
};

Si vous remplacez Container, par un modèle de paramètre du modèle, pourquoi voulez-vous obtenir?

template <typename T, template <typename...> class Container>
struct stack {
    Container<T> container;
};

Vous êtes l'instanciation Container qu'une seule fois et uniquement pour T (Container<T>), donc il n'y a aucun avantage pour un modèle de paramètre du modèle.

Pourquoi est-il plus restrictive?

Avec un modèle de paramètre du modèle, vous devez passer à l' std::stack un modèle qui exposent la même signature, par ex.:

template <typename T, template <typename> class Container>
struct stack;

stack<int, std::vector> // Error: std::vector takes two template arguments

Peut-être que vous pourriez utiliser variadic templates:

template <typename T, template <typename....> class Container>
struct stack {
    Container<T> container;
};

stack<int, std::vector> // Ok, will use std::vector<int, std::allocator<int>>

Mais que faire si je ne veux pas utiliser la norme std::allocator<int>?

template <typename T, 
          template <typename....> class Container = std::vector, 
          typename Allocator = std::allocator<T>>
struct stack {
    Container<T, Allocator> container;
};

stack<int, std::vector, MyAllocator> // Ok...

Cela devient un peu brouillon... Que faire si je veux utiliser mon propre conteneur des modèles qui prend les 3/4/N paramètres?

template <typename T,
          template <typename... > class Container = std::vector,
          typename ...Args>
struct stack {
    Container<T, Args...> container;
};

stack<int, MyTemplate, MyParam1, MyParam2> // Ok...

Mais, que faire si je veux utiliser un non-basé sur un modèle de conteneur?

struct foo { };
struct foo_container{ };

stack<foo, foo_container> // Error!

template <typename... >
using foo_container_template = foo_container;

stack<foo, foo_container_template> // Ok...

Avec un paramètre de type, il n'y a pas de telles questions1:

stack<int>
stack<int, std::vector<int, MyAllocator<int>>
stack<int, MyTemplate<int, MyParam1, MyParam2>>
stack<foo, foo_container>

1 Il y a d'autres cas qui ne fonctionne pas avec le modèle modèle de paramètre, par exemple à l'aide de modèles acceptant un mélange du type et de la non-paramètres de type de commandes spécifiques, pour lesquels vous pouvez créer de modèle générique de paramètre du modèle, même à l'aide de variadic templates.

18voto

nate Points 1

À l'aide d'un modèle de paramètre de modèle permettrait de restreindre les types que vous pouvez utiliser comme conteneur sous-jacent à ceux qui exposent le même modèle signature. Ce formulaire permet à des types arbitraires, aussi longtemps qu'ils en charge l'interface attendue.

13voto

Konrad Rudolph Points 231505

Parce qu'il ne veut pas compiler:

std::deque n'est pas de type

template <typename T> class std::deque

il est de type

template<class T, class Alloc> class std::deque

Bien sûr, cela est un problème plus général: même si nous étions à fournir à l' Alloc paramètre de modèle à notre - stack modèle de classe, la classe devrait maintenant fonctionner uniquement avec des conteneurs qui ont exactement deux gabarit de type d'arguments. C'est une restriction déraisonnable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X