8
votes

Pourquoi moins que l'opérateur accepte différents types de paramètres tandis que STD :: min ne pas?

> In file included from /usr/include/c++/4.8/bits/char_traits.h:39:0,
>                  from /usr/include/c++/4.8/ios:40,
>                  from /usr/include/c++/4.8/ostream:38,
>                  from /usr/include/c++/4.8/iostream:39,
>                  from sum_to.cpp:1: /usr/include/c++/4.8/bits/stl_algobase.h:239:5: note: template<class
> _Tp, class _Compare> const _Tp& std::min(const _Tp&, const _Tp&, _Compare)
>      min(const _Tp& __a, const _Tp& __b, _Compare __comp)
>      ^ /usr/include/c++/4.8/bits/stl_algobase.h:239:5: note:   template argument deduction/substitution failed: sum_to.cpp:7:29:
> note:   deduced conflicting types for parameter ‘const _Tp’ (‘int’ and
> ‘long long int’)
>      std::cout<<std::min(a, b);

---

1 commentaires

Parce que fait conversions en compte.


5 Réponses :


7
votes

5 commentaires

Pourriez-vous s'il vous plaît donner une référence spécifique à << / code>? J'ai compris promotions mais je ne peux pas savoir pourquoi << / code> convient à ce Promotions .


@Kamel C'est le cas pour tous les opérateurs arithmétiques intégrés ( lien ).


J'ai lu le document de Java pour apprendre à utiliser son SDK, tout en lisant le document C ++ pour apprendre comment son compilateur ticks à exécuter le code.


@Kamel si vous voulez dire que c ++ est inégalé, ce n'est pas. C'est juste beaucoup plus complexe que Java, et vous devez en savoir plus de ses morceaux pour voir qu'ils correspondaient bien ensemble.


L'héritage de C. Appelez cela la malédiction de la compatibilité à l'envers avec le code remontant 3 décennies.



2
votes

C'est parce que std :: min code> est une fonction de modèle.

template <class T> const T& min (const T& a, const T& b) {
  return !(b<a)?a:b;     // or: return !comp(b,a)?a:b; for version (2)
}


0 commentaires

-1
votes

Les types primitifs ne surchargent pas les opérateurs de surcharge, les les conversions arithmétiques habituelles sont appliquées et votre INT est converti en une longue longue et le "<" a une signification valide.

Vous ne pouvez même pas surcharger des opérateurs pour des types primitifs: https://isocpp.org/wiki/faq/intrinsic-types # Intrinsics-and-Opérateur-Overloading

Exemple Pour montrer que votre INT est favorisé à long long xxx

documentation http://en.cppreference.com/w/cpp/language/operator_arithmetic

pour les opérateurs binaires (sauf quarts de travail), si les opérandes promus avoir des types différents, un ensemble supplémentaire de conversions implicites est appliqué, connu sous le nom de conversions arithmétiques habituelles avec le but de produire le type commun (également accessible via le type STD :: Common_Type TRAIT)


2 commentaires

Chaque paire de types d'arithmétiques promus a des opérateurs définis pour cette paire. int est déjà un type arithmétique favorisé. La promotion ne produit rien avec un rang supérieur à int sauf s'il ne change pas le type. int -> long long n'est pas une promotion valide.


S'il vous plaît vérifier ma réponse mise à jour, je crains que votre commentaire ne reflète pas ce qui se passe en réalité. «Promuté» peut ne pas avoir été le bon terme, mais des "conversions arithmétiques habituelles" sont appliquées.



-1
votes

L'opérateur << / code> est binaire, le compilateur pourrait donc convertir des arguments vers le même type et les comparer.

sinon min doit renvoyer quelque chose. Comment le compilateur pourrait-il deviner quel type devrait-il revenir?


0 commentaires

3
votes

Comme expliqué dans d'autres réponses, la raison est que std :: min code> nécessite que les types d'arguments soient identiques si la déduction doit être effectuée, tandis que implique Les conversions arithmétiques habituelles (§5.9 / 2), qui veilleront à ce que les types soient convertis en un "dénominateur commun". Notez comment §13.6 / 12 énumère les opérateurs intégrés en tant que candidats:

pour chaque paire de types arithmétiques promus l code> et r code>, il existe Fonctions de l'opérateur candidat de la forme p>

template <typename T>
constexpr decltype(auto) min(T&& t) {return std::forward<T>(t);}

template <typename T, typename U, typename... Args>
constexpr auto min(T&& t, U&&u, Args&&... args) {
    std::common_type_t<T, U> const& _t(std::forward<T>(t)), _u(std::forward<U>(u));
    return min(_t<_u? _t : _u, std::forward<Args>(args)...);
}


3 commentaires

N'est pas t susceptible de convertir t et u sur common_type_t (pour primitif les types)? Eh bien, cela ne fera pas de copie dans certains cas comme votre code ci-dessus fera: cela peut toutefois être corrigé avec un peu plus d'effort.


@Yakk j'ai essayé autre chose. Cependant, il pourrait y avoir un opérateur << / code> qui compare des types de classe distincts. Ensuite, a effectue seulement deux copies à Common_Type , tandis que le mien effectue trois en tout cas. Je ne suis pas si dérangé par les types primitifs, car je pense que les compilateurs optimisent en conséquence pour ceux-ci.


Si nous n'appliquons pas l'ordre de << / code> (raisonnable), et notre min renvoie une référence (dans la mesure du possible), alors min (A, B, c. ..) étant auto && x = min (avant (b), avant (c) ...); Retour no_rvalue (A , où no_rvalue convertit les avales en valeurs et laisse seules les livres? Je suppose que si b est un rvalue et c ... est vide, cela provoque une copie supplémentaire. gah. Besoin de distinguer entre les vrais temporaires (locaux) et les temporaires passés? Pour éviter des copies supplémentaires.