Il ya quelque temps, j'ai lu un article qui expliquait plusieurs pièges de la recherche dépendant d'un argument, mais je ne le trouve plus. Il s'agissait d'avoir accès à des choses auxquelles vous n'auriez pas accès ou quelque chose comme ça. Alors j'ai pensé que je demanderais ici: quels sont les pièges de l'ADL?Quels sont les pièges de l'ADL?
Répondre
Il y a un énorme problème avec la recherche dépendant de l'argument. Considérons, par exemple, l'utilitaire suivant:
#include <iostream>
namespace utility
{
template <typename T>
void print(T x)
{
std::cout << x << std::endl;
}
template <typename T>
void print_n(T x, unsigned n)
{
for (unsigned i = 0; i < n; ++i)
print(x);
}
}
C'est assez simple, non? Nous pouvons appeler print_n()
et passer un objet et il appellera print
pour imprimer l'objet n
fois.
En fait, il se trouve que si on ne regarde que ce code, nous avons absolument aucune idée quelle fonction sera appelée par print_n
. Il peut s'agir du modèle de fonction print
donné ici, mais ce n'est peut-être pas le cas. Pourquoi? Recherche dépendante de l'argument. Par exemple, imaginons que vous ayez écrit une classe pour représenter une licorne. Par exemple, disons que vous avez écrit une classe pour représenter une licorne. Pour une raison quelconque, vous avez également défini une fonction nommée print
(quelle coïncidence!) Qui provoque simplement le blocage du programme en écrivant à un pointeur nul déréférencé (qui sait pourquoi vous l'avez fait, ce n'est pas important):
namespace my_stuff
{
struct unicorn { /* unicorn stuff goes here */ };
std::ostream& operator<<(std::ostream& os, unicorn x) { return os; }
// Don't ever call this! It just crashes! I don't know why I wrote it!
void print(unicorn) { *(int*)0 = 42; }
}
Ensuite, vous écrivez un petit programme qui crée une licorne et imprime quatre fois:
int main()
{
my_stuff::unicorn x;
utility::print_n(x, 4);
}
vous compilez ce programme, exécutez, et ... il se bloque. "Quoi?", Vous dites: "Je viens d'appeler print_n
, qui appelle la fonction print
pour imprimer la licorne quatre fois!" Oui, c'est vrai, mais il n'a pas appelé la fonction print
que vous vous attendiez à appeler. C'est ce qu'on appelle my_stuff::print
.
Pourquoi my_stuff::print
est sélectionné? Lors de la recherche de nom, le compilateur voit que l'argument de l'appel à print
est de type unicorn
, qui est un type de classe déclaré dans l'espace de noms my_stuff
.
En raison de la recherche dépendant de l'argument, le compilateur inclut cet espace de noms dans sa recherche de fonctions candidates nommées print
. Il trouve my_stuff::print
, qui est ensuite sélectionné comme meilleur candidat viable pendant la résolution de surcharge: aucune conversion n'est requise pour appeler l'une des fonctions print
candidates et les fonctions non-modèles sont préférées aux modèles de fonction, donc la fonction non-estimée my_stuff::print
est la meilleure correspondance.
(Si vous ne croyez pas, vous pouvez compilez le code dans cette question comme ça, et voir ADL en action.)
Oui, la recherche dépendante argument est une caractéristique importante de C++. Il est essentiellement nécessaire d'atteindre le comportement souhaité de certaines fonctionnalités de langage comme les opérateurs surchargés (considérez la bibliothèque de flux). Cela dit, c'est aussi très, très imparfait et peut conduire à des problèmes vraiment laids. Il y a eu plusieurs propositions pour corriger la recherche dépendant des arguments, mais aucune d'entre elles n'a été acceptée par le comité des normes C++.
- 1. Quels sont les pièges et les solutions lors de la configuration de Rails/Mysql sur Leopard?
- 2. Naming and Directory (JNDI) - Quels sont les pièges à l'aide de JNDI
- 3. Quels sont les inconvénients des gros binaires?
- 4. Quels sont les attributs?
- 5. pièges cachés de VBA
- 6. auto_ptr Pièges et pièges
- 7. Quels sont les pièges de la combinaison d'un projet de site Web avec un projet d'application Web dans Visual Studio?
- 8. Quels sont les services .NET?
- 9. Quels sont les déclencheurs d'interaction?
- 10. Quels sont les avantages de Struts
- 11. Quels sont les avantages/inconvénients de py2exe
- 12. Quels sont les principaux concurrents de Servoy?
- 13. Quels sont les concepts avancés de Velocity?
- 14. Quels sont les bons diagrammes de carte?
- 15. Quels sont les arbres de résultats XSLT
- 16. Quels sont les types de données JavaScript?
- 17. Quels sont les fichiers .pidb de MonoDevelop?
- 18. Quels sont les codes de balayage pour:
- 19. Quels sont les avantages de VS2010 SP1?
- 20. De MySQL, aller à Oracle: les pièges
- 21. Quels sont les os d'un CMS puissant
- 22. Quels sont les inconvénients des méthodes statiques?
- 23. Quels sont les problèmes résolus par Maven?
- 24. Quels sont les cas d'utilisation AOP possibles?
- 25. Quels sont les deuxièmes moments d'une région?
- 26. Quels sont les plugins recommandés pour Trac?
- 27. Quels sont les bons tutoriels Wireshark?
- 28. Quels sont les avantages d'utiliser MSBuild?
- 29. Quels sont les dégâts subis par document.write()?
- 30. Quels sont les meilleurs thèmes Silverlight?
Je devrais probablement noter que cet exemple a été inspiré par une présentation sur le sujet que Bartosz Milewski a donné; Je n'ai pas les diapositives de cette présentation, et ce n'est pas exactement la même chose, mais c'est proche. –
Est-ce un piège des AVQ ou un piège de ne pas utiliser ADL soigneusement? – Chubsdad
@ Chubsdad: C'est un énorme piège de l'ADL. Le problème est que vous pouvez écrire deux bibliothèques qui sont totalement indépendantes et accidentellement confrontées à ce problème sans avoir aucune idée que vous allez avoir des problèmes. Aucune "prudence" ne peut vous protéger complètement de cela. –