Quelle est la relation entre le modèle C ++ et la frappe de canard?

Pour moi, le modèle C ++ utilise l’idée de la frappe au canard, est-ce exact? Cela signifie-t-il que tous les types génériques référencés dans la classe ou la méthode de modèle sont de type canard?

Pour moi, le modèle C ++ utilise l’idée de la frappe au canard, est-ce exact?

Non, les modèles C ++ sont utilisés pour implémenter le code générique. Autrement dit, si votre code peut fonctionner avec plusieurs types, vous n’avez pas à le dupliquer pour chaque type. Des choses comme std::vector et std::list sont des exemples évidents. Les modèles C ++ ont été abusés pour faire autre chose, mais la généricité était l’intention initiale.

Cela signifie-t-il que tous les types génériques référencés dans la classe ou la méthode de modèle sont de type canard?

Non, ce ne sont que des types “normaux”, comme tous les autres types en C ++. Ils ne sont tout simplement pas connus jusqu’à ce que le modèle soit réellement instancié.

Cependant, les modèles peuvent être utilisés pour implémenter quelque chose comme la frappe au canard. Les iterators sont un exemple. Considérons cette fonction:

 template OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) { while (first!=last) *result++ = *first++; return result; } 

Notez que la fonction copy peut accepter des arguments de tout type , de la même manière qu’elle implémente l’opérateur d’inégalité, l’opérateur de déréférence et l’opérateur d’incrémentation de postfix. C’est probablement aussi proche de la saisie manuelle que vous obtiendrez en C ++.

Pour moi, les modèles C ++ sont une version à la compilation du dactylographie. Le compilateur comstackra par exemple Class et tant que votre canard aura tous les types nécessaires, il instanciera une classe.

Si quelque chose n’est pas correct (par exemple, un constructeur de copie manquant), la compilation échoue. La contrepartie de ducktyping réel est un échec lorsque vous appelez une fonction avec un type non-canard. Et ici, cela se produirait au moment de l’exécution.

Taper sur un canard signifie “s’il charrie comme un canard et marche comme un canard, alors c’est un canard”. En informatique, il n’existe pas de définition formelle permettant de comparer le C ++.

C ++ n’est pas identique à (par exemple) Python, bien sûr, mais ils ont tous deux un concept d’interfaces implicitement définies. L’interface requirejse d’un object utilisé comme argument de fonction Python est celle que la fonction en fasse. L’interface requirejse d’un type utilisé comme argument de modèle C ++ est celle utilisée par le modèle avec des objects de ce type. C’est la similitude et c’est sur ce motif que les modèles C ++ doivent être évalués.

De plus, en raison de la déduction des arguments de modèle, en C ++, vous pouvez essayer de transmettre tout ancien object. Le compilateur déterminera s’il peut instancier le modèle de fonction.

Une différence réside dans le fait qu’en C ++, si l’argument ne s’affranchit pas, les objects du compilateur. En Python, seuls les objects d’exécution (et uniquement si la fonction est réellement appelée, s’il y a des conditions dans le code). Il s’agit d’une différence dans la nature de l’interface demandée pour un object / type – en C ++, le modèle nécessite la validité d’une expression particulière ou ne le requirejs pas. En Python, les expressions valides nécessaires peuvent dépendre des valeurs d’exécution des expressions nécessaires antérieures. Ainsi, en Python, vous pouvez demander un object qui convole fort ou silencieusement. S’il le fait bruyamment, il doit également marcher. En C ++, vous pouvez le faire avec un dynamic_cast conditionnel. Si le volume est une constante de compilation, vous pouvez le faire avec des spécialisations de modèles, mais vous ne pouvez pas utiliser le typage statique pour indiquer qu’un canard doit marcher s’il quack_volume() loud . Et bien sûr, en Python, l’interface requirejse peut ne pas être réellement “obligatoire” – le comportement en l’absence de méthode consiste à émettre une exception. Il peut également être possible de documenter et de garantir le comportement de l’appelant.

À vous de décider si vous définissez le “dactylographie” de sorte que cette différence signifie que C ++ ne l’a pas.

Pas exactement. Les types de canard (style de type dynamic) ne généreront jamais d’erreurs de type à la compilation car ils n’ont tout simplement aucun type. Avec les modèles, vous n’avez pas de types jusqu’à ce que vous instanciez le modèle. Une fois que vous le faites, les variables ont des types distincts et vous obtiendrez effectivement des erreurs de compilation.

De plus, avec les types de canard, vous pouvez avoir une variable qui pointe vers différents types d’objects, car les variables n’ont tout simplement pas de types. Ce n’est pas possible avec les modèles – une fois que vous les instanciez, les variables ont un type spécifique unique.

Elles sont similaires, toutefois, en ce sens que les contraintes sont implicites: seules les fonctionnalités réellement utilisées sont vérifiées. Contrairement aux pointeurs polymorphes, par exemple, le type réel importe peu.

Oui, en quelque sorte – par exemple, si le type X a les AddRef() , Release() et QueryInterface() avec les signatures appropriées, vous pouvez l’utiliser comme object COM avec la classe de modèle CComPtr . Mais ce n’est pas complet, la vérification du type est toujours appliquée pour les parameters.

Non, c’est un concept différent. La saisie de type de canard est une méthode permettant de connaître le type d’un conteneur typé dynamic. Les modèles C ++ ne sont pas typés de manière dynamic, ils sont instanciés avec un type spécifique.

Wikipedia couvre cette distinction .