2009-12-16 3 views
2

J'ai actuellement un modèle de fonction, en prenant une référence, qui fait quelque chose en substance équivalente à:Traitement des références dans les modèles de C

template <typename T> 
void f(T& t) 
{ 
    t = T(); 
} 

Maintenant, je peux appeler:

int a; 
f(a); 

Pour initialiser ma variable a. Je peux même faire:

std::vector<int> a(10); 
f(a[5]); 

Cependant, cela échouera:

std::vector<bool> a(10); 
f(a[5]); 

La raison d'être a[5] retourne un objet en référence sémantique, mais pas une référence. Donc, je dois pouvoir écrire:

template <typename T> 
void f(T a) 
{ 
    a = T(); 
} 

Mais si j'ajoute ce nouveau modèle et essayer de compiler le premier exemple (avec int), j'obtiens l'erreur suivante:

test_multi_tmpl.cc: In function ‘int main()’: 
test_multi_tmpl.cc:20: error: call of overloaded ‘f(int&)’ is ambiguous 
test_multi_tmpl.cc:6: note: candidates are: void f(T&) [with T = int] 
test_multi_tmpl.cc:12: note:     void f(T) [with T = int] 

Toutes les idées comment résoudre ceci? Je ne voudrais pas surcharger f juste pour std::vector<bool>::reference car cette construction pourrait apparaître dans d'autres endroits ...

Répondre

4

Je pense que la spécialisation f pour std::vector<bool>::reference est votre seule option.

Notez que l'utilisation std::vector<bool> est probablement une mauvaise idée en premier lieu (la spécialisation std::vector<bool> est dépréciée pour les versions futures du langage C++) de sorte que vous pouvez simplement utiliser std::deque<bool> à la place. L'utilisation de traits ou d'une spécialisation de gabarit ferait en sorte que cela fonctionne.

+0

'vecteur ' peut fonctionner aussi. –

+1

'vecteur ' serait techniquement plus proche. –

+0

La spécialisation 'std :: vector ' est en effet déconseillée, mais pourquoi arrêter d'utiliser un vecteur de booléens? –

0

+0

Je suppose qu'il veut que cela fonctionne pour n'importe quel "type de référence", et pas seulement pour le "vecteur :: reference". Et quels traits utiliseriez-vous ici? –

1

Il y a deux façons de le faire, l'une est, comme vous le suggérez, spécialisée pour std::vector<bool>::reference. L'autre est en utilisant la répartition des caractères de type.

template <class T> 
void f (T& t) { 
    f_impl(t, is_reference_wrapper_type<T>()); 
} 

template <class T> 
void f_impl(T& t, mpi::false_) { 
    t = T(); 
} 

template <class T> 
void f_impl(T& t, mpi::true_) { 
    // do nothing, or voodoo here 
} 

Notez le code ci-dessus est non testé et il y aurait des moyens plus complexes de dispatching basé sur un trait - ou un ensemble de traits - dans cette situation.

Cela voudrait dire aussi que vous auriez besoin de mettre en œuvre is_reference_wrapper_type comme ceci:

template <class T> 
struct is_reference_wrapper_type : mpi::false_ {}; 

template <> 
struct is_reference_wrapper_type<std::vector<bool>::reference> : mpi::true_ {}; 
+0

Cela ne fonctionnerait pas, comme avec votre code, si j'appelle 'int a; f (a); ', qui n'utilisera jamais a comme référence. – PierreBdR

+0

Oh, vous avez raison. Laisse-moi éditer pour le réparer. –

+0

mmmhh ... en fait, cela ne résout pas le problème! Cela ne permet toujours pas ceci: le vecteur a (10); f (a [5]); – PierreBdR

1

Je ne sais pas si vous connaissez déjà ce ...

std :: spécialisation vecteur est pas vraiment un conteneur STL car il ne pas répondre aux exigences nécessaires. En particulier, il n'est pas possible de créer des conteneurs mandatés qui satisfont le STL concepts en raison de la sémantique de référence (vous ne pouvez pas simuler une référence). Vérifiez this article pour plus d'informations. (En outre, comme Autopulated mentionné il devrait y avoir une directive du compilateur pour fournir un contrôle sur std :: vecteur dans le futur C++ standard.)

Une solution simple qui pourrait résoudre votre problème est en surchargeant la fonction f pour ce type particulier (et d'autres s'ils apparaissent et ne sont pas nombreux).Notez qu'il s'agit d'une surcharge et pas une spécialisation . Vous pourriez également vouloir vérifier ceci pour why not specialize function templates.


void f(std::vector<bool>::reference t) 
{ 
    /* ... */ 
} 
+0

Je sais que je pourrais surcharger. Mais comme je l'ai dit, je ne * le * ferais pas. Pour un, cela ne fonctionnerait que pour ce cas particulier, et aussi, ce n'est pas vraiment une fonction, mais une méthode dans mon cas. Donc je ne peux pas avoir toutes les méthodes possibles dans la classe. – PierreBdR

Questions connexes