Je souhaite transmettre une fonction surchargée à l' std::for_each()
algorithme. Par exemple,
class A {
void f(char c);
void f(int i);
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), f);
}
};
Je m'attendrais à ce que le compilateur résolve f()
par le type d'itérateur. Apparemment, cela (GCC 4.1.2) ne le fait pas. Alors, comment puis-je spécifier ce que f()
je veux?
Réponses:
Vous pouvez utiliser
static_cast<>()
pour spécifier lequelf
utiliser en fonction de la signature de fonction impliquée par le type de pointeur de fonction:Ou, vous pouvez également faire ceci:
S'il
f
s'agit d'une fonction membre, vous devez utilisermem_fun
, ou pour votre cas, utiliser la solution présentée dans cet article de Dr. Dobb .la source
f()
est membre d'une classe (voir l'exemple modifié ci-dessus)reinterpret_cast
. Le plus souvent, je vois des moulages de style C utilisés pour cela. Ma règle est simplement que les casts sur des pointeurs de fonction sont dangereux et inutiles (comme le montre le deuxième extrait de code, une conversion implicite existe).std::for_each(s.begin(), s.end(), static_cast<void (A::*)(char)>(&A::f));
Lambdas à la rescousse! (Remarque: C ++ 11 requis)
Ou en utilisant decltype pour le paramètre lambda:
Avec des lambdas polymorphes (C ++ 14):
Ou dissipez l'ambiguïté en supprimant la surcharge (ne fonctionne que pour les fonctions gratuites):
la source
mem_fn
etbind
, qui, BTW. Sont également C ++ 11). Aussi, si nous voulons devenir vraiment pédant,[&](char a){ return f(a); }
c'est 28 caractères etstatic_cast<void (A::*)(char)>(&f)
35 caractères.Pourquoi ça ne marche pas
Ce serait génial si c'était le cas! Cependant,
for_each
est un modèle de fonction, déclaré comme:La déduction de modèle doit sélectionner un type pour
UnaryFunction
au moment de l'appel. Maisf
n'a pas de type spécifique - c'est une fonction surchargée, il y en a beaucoupf
avec chacun des types différents. Il n'existe actuellement aucun moyen pourfor_each
faciliter le processus de déduction du modèle en indiquant cef
qu'il veut, donc la déduction du modèle échoue tout simplement. Pour que la déduction du modèle réussisse, vous devez travailler davantage sur le site d'appel.Solution générique pour le réparer
Sauter ici quelques années et C ++ 14 plus tard. Plutôt que d'utiliser un
static_cast
(qui permettrait à la déduction de modèle de réussir en "corrigeant" ce quef
nous voulons utiliser, mais vous oblige à faire manuellement une résolution de surcharge pour "corriger" la bonne), nous voulons que le compilateur fonctionne pour nous. Nous voulons faire appelf
à certains arguments. De la manière la plus générique possible, c'est:C'est beaucoup à taper, mais ce genre de problème survient fréquemment, nous pouvons donc simplement l'envelopper dans une macro (soupir):
puis utilisez-le simplement:
Cela fera exactement ce que vous souhaitez que le compilateur fasse - effectuer une résolution de surcharge sur le nom
f
lui-même et faire ce qu'il faut. Cela fonctionnera indépendamment du fait qu'il s'agisse d'f
une fonction libre ou d'une fonction membre.la source
Pas pour répondre à ta question, mais suis-je le seul à trouver
à la fois plus simple et plus court que l'
for_each
alternative proposée par in silico dans ce cas?la source
Le problème ici ne semble pas être la résolution de surcharge, mais en fait la déduction des paramètres de modèle . Alors que l' excellente réponse de @In silico résoudra un problème de surcharge ambigu en général, il semble que la meilleure solution lorsqu'il s'agit de
std::for_each
(ou similaire) est de spécifier explicitement ses paramètres de modèle :la source
Si cela ne vous dérange pas d'utiliser C ++ 11, voici une aide intelligente qui est similaire (mais moins moche que) à la distribution statique:
(Fonctionne pour les fonctions membres; devrait être évident comment le modifier pour qu'il fonctionne pour les fonctions autonomes, et vous devriez être en mesure de fournir les deux versions et le compilateur sélectionnera la bonne pour vous.)
Merci à Miro Knejp d'avoir suggéré: voir aussi https://groups.google.com/a/isocpp.org/d/msg/std-discussion/rLVGeGUXsK0/IGj9dKmSyx4J .
la source
R
, ce n'est pas déduit. Il n'y a pas non plus de mention de cela dans cette réponse.R
, je fournisArgs
.R
etT
sont déduits. Il est vrai que la réponse pourrait être améliorée. (Il n'y a pasT
dans mon exemple cependant, car ce n'est pas un pointeur vers un membre, car cela ne fonctionnerait pas avecstd::for_each
.)