47 votes

Répartition des tags par rapport aux méthodes statiques sur des classes partiellement spécialisées

Supposons que je veuille écrire une fonction générique void f<T>(), ce qui ne fait qu'une chose si T est un type POD et une autre chose si l' T est non-POD (ou tout autre arbitraire prédicat).

Une façon d'y parvenir serait d'utiliser une balise d'expédition modèle comme la bibliothèque standard ne avec itérateur catégories:

template <bool> struct podness {};
typedef podness<true> pod_tag;
typedef podness<false> non_pod_tag;

template <typename T> void f2(T, pod_tag) { /* POD */ }
template <typename T> void f2(T, non_pod_tag) { /* non-POD */ }

template <typename T>
void f(T x)
{
    // Dispatch to f2 based on tag.
    f2(x, podness<std::is_pod<T>::value>());
}

Une alternative serait d'utiliser la fonction membre statique d'partiellement spécialisés types:

template <typename T, bool> struct f2;

template <typename T>
struct f2<T, true> { static void f(T) { /* POD */ } };

template <typename T>
struct f2<T, false> { static void f(T) { /* non-POD */ } };

template <typename T>
void f(T x)
{
    // Select the correct partially specialised type.
    f2<T, std::is_pod<T>::value>::f(x);
}

Quels sont les avantages et les inconvénients de l'utilisation d'une méthode plutôt que l'autre? Qui recommanderiez-vous?

15voto

Alexandre C. Points 31758

Un lisible alternative à l' [boost|std]::enable_if, de balises et de spécialisation partielle pour la simple compilation d'expédition que j'aime est la suivante:

[N'oubliez pas que les booléens ont de conversion de nombres entiers, de longueur nulle tableaux sont invalides et que délinquance des modèles sont mis au rebut (SFINAE). Aussi, char (*)[n] est un pointeur vers un tableau d' n éléments.]

template <typename T> 
void foo(T, char (*)[is_pod<T>::value] = 0)
{
    // POD
}

template <typename T> 
void foo(T, char (*)[!is_pod<T>::value] = 0)
{
    // Non POD
}

Il a aussi l'avantage de ne pas avoir de classes externes, qui polluent l'espace de noms. Maintenant, si vous voulez externaliser le prédicat, comme dans votre question, vous pouvez le faire:

template <bool what, typename T>
void foo(T, char (*)[what] = 0)
{
    // taken when what is true
}

template <bool what, typename T>
void foo(T, char (*)[!what] = 0)
{
    // taken when what is false
}

Utilisation:

foo<std::is_pod<T>::value>(some_variable);

15voto

tim Points 332

Je voudrais étiquette d'expédition parce que:

  • Facile à étendre avec de nouvelles balises
  • Facile à utiliser l'héritage (exemple)
  • Il est assez courant de la technique de programmation générique

Il semble difficile pour moi d'ajouter un troisième variante, dans le deuxième exemple. Quand vous aurez envie d'ajouter, par exemple la non-POD-de-Gousses de type que vous aurez à remplacer bool en template <typename T, bool> struct f2; avec autre chose (int si vous le souhaitez =) ) et de le remplacer tous struct f2<T, bool-value> avec struct f2<T, another-type-value>. De sorte que, pour moi, la deuxième variante semble difficilement extensible. Veuillez me corriger si j'ai tort.

10voto

legends2k Points 6380

En fait les deux sont de la balise expédition modèle seulement. L'ancien est appelé tag envoi en instance et le dernier est une balise envoi par type.

Barend, le principal auteur de Boost.La géométrie, explique à la fois les méthodes et préfère celui-ci. Il est utilisé dans les Stimuler.La géométrie en profondeur. Voici les avantages en résumé:

  • Il est inutile d'instancier la balise puisque son seul but est de se différencier
  • Il est facile de définir de nouveaux types et constantes basée sur les balises
  • Les Arguments peut être inversé dans l'interface, c'est à dire dire distance(point, polygon); et distance(polygon, point); peut à la fois avoir un seul de la mise en œuvre

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