J'ai un problème où je voudrais fournir une version générique d'une fonction foo code> qui ne peut être appliquée que lorsqu'il n'y a absolument aucune autre correspondance pour une invocation. Comment puis-je modifier le code suivant de telle que last_resort :: foo code> est une correspondance pire pour dérivé :: Type code> que base :: foo code>? J'aimerais trouver une solution qui n'implique pas de modifier la définition de la barre code> et qui préserverait le type de l'argument de last_resort :: FOO code>. #include <iostream>
namespace last_resort
{
template<typename T> void foo(T)
{
std::cout << "last_resort::foo" << std::endl;
}
}
template<typename T> void bar(T)
{
using last_resort::foo;
foo(T());
}
namespace unrelated
{
struct type {};
}
namespace base
{
struct type {};
void foo(type)
{
std::cout << "base::foo" << std::endl;
}
}
namespace derived
{
struct type : base::type {};
}
int main()
{
bar(unrelated::type()); // calls last_resort::foo
bar(base::type()); // calls base::foo
bar(derived::type()); // should call base::foo, but calls last_resort::foo instead
return 0;
}
4 Réponses :
Vous ne pouvez pas faire grand chose à ce sujet. Les deux fonctions FOO sont dans l'ensemble de surcharge. Mais votre Last_Resort One est un meilleur match simplement parce qu'il ne nécessite pas de conversion contrairement à la base :: FOO pour dérivé :: Type (). Ce n'est que dans le cas où deux candidats sont "tout aussi bien" à juger par les paramètres et les conversions possibles, un non-modèle est préféré. P>
C'est vrai, mais je me demande s'il y a un moyen d'introduire une conversion "cachée" en foo en augmentant celui-ci avec des paramètres supplémentaires avec des valeurs par défaut?
Je ne pense pas que ça va marcher. D'après ce que je peux dire au "meilleur" que vous puissiez obtenir est une ambiguïté afin que la compilation échoue. Mais peut-être, il me manque aussi quelque chose.
La solution semble être de décorer le type de retour Last_Resort :: FOO code> S avec quelque chose comme Désactiver_if_foo_exists last_resort :: FOO code> serait supprimé de l'ensemble de la surcharge.
Vous pouvez fournir une surcharge de la barre code> pour type dérivé :: Type Code> Après la déclaration de dérivé :: Type Code>. Cela peut être dans Espace de noms dérivé code> ou non. void bar(derived::type)
{
foo(derived::type());
}
Ce serait à peu près aussi mauvais que possible:
struct badParam {
badParam() { }
operator int() { return 42; }
};
namespace last_resort {
template <typename T> void foo(T t, int dummy = badParam(), ...) {
std::cout << "last_resort::foo" << std::endl;
}
}
Merci. Je pense que l'ajout du Badparam code> est suffisante pour la modifier, mais elle efface le type de t code> dans la conversion.
Eh bien, pour un dernier cas, vous ne pouvez généralement pas compter sur T de toute façon, car vous obtenez tous les types étranges. Mais le sauvegarde est difficile. La déduction de l'argument de modèle ne produit pas ces conversions définies par l'utilisateur.
Post antique, mais la pensée aléatoire: que diriez-vous d'utiliser l'original badparam code>, mais faisant Badparam code> un type de modèle avec un argument de modèle Pointeur de valeur sur la fonction réelle pour invoquer, ce qu'il fait donc dans son constructeur.
la sortie: p> < pré> xxx pré> Cette réponse explique comment construire une solution pour vérifier l'existence d'une fonction ( Last_Resort :: FOO code> peut être supprimé de l'ensemble de surcharge avec désactiver_if code>. L'idée est de désactiver last_resort :: foo (t) code> si foo (t) code> est autrement bien formé. Ceci provoque last_resort :: FOO (t) code> Pour être la pire match pour FOO code>: foo code>) renvoyant vide code>. P> p> p>