2015-08-11 12 views
8
#include <iostream> 

int main(){ 
    int a = 1; 
    long long b = 2; 
    std::cout<<(a<b); 
    std::cout<<std::min(a, b); 
    return 0; 
} 

> 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); 

--- 

Dank chris Kommentar in function overloading post Vorlage Argument Abzug erfolgt nicht Conversions berücksichtigt. Ein Vorlagenparameter kann nicht mit zwei Typen übereinstimmenWarum weniger als Operator akzeptiert verschiedene Arten von Parametern während std :: min nicht?

So std::min fehlgeschlagen.

Warum < würde funktionieren?

+3

Weil * Konvertierungen berücksichtigt werden. – molbdnilo

Antwort

7

Da die integrierte < gilt Numeric promotions, und Vorlage Argument Abzug nicht.

+1

Könnten Sie bitte einen Verweis spezifisch auf '<' geben? Ich habe "Promotions" verstanden, kann aber nicht herausfinden, warum "<" für diese "Promotions" geeignet ist. – Kamel

+1

@Kamel Das ist bei allen integrierten arithmetischen Operatoren der Fall ([link] (http://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversions)). – Quentin

+0

Ich lese das Java-Dokument, um zu lernen, wie man sein SDK benutzt, während ich das C++ - Dokument lese, um zu erfahren, wie sein Compiler den Code ausführt. – Kamel

2

Es ist, weil std::min eine Vorlagenfunktion ist.

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) 
} 

so muss sie die Argumente die gleiche Art haben, aber wenn man (a<b) verwenden, so könnte a implizit auf einen nicht überlasten Betreiber long long

-1

Primitive Typen umgewandelt, so Die üblichen arithmetischen Umwandlungen werden angewendet und Ihr int wird in einen langen long konvertiert, und der "<" hat eine gültige Bedeutung.

Sie können nicht einmal Betreiber Überlastung für primitive Typen: https://isocpp.org/wiki/faq/intrinsic-types#intrinsics-and-operator-overloading

Beispiel zu zeigen, dass Ihr int zu lange lange

gefördert wird
// common_type example 
#include <iostream> 
#include <type_traits> 

int main() { 

    typedef std::common_type<int, long long>::type A;   // i 
    std::cout << "A: " << std::is_same<long long,A>::value << std::endl; 

    return 0; 
} 

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

Für die binäre Operatoren (außer Verschiebungen), wenn die beförderten Operanden diff haben Erent Typen zusätzlicher Satz von impliziten Konvertierungen angewandt, bekannt als üblichen arithmetischen Umwandlungen mit dem Ziel zu erzeugen, den gemeinsamen Typ (auch über die std :: common_type Typ trait)

+0

Für jedes Paar von hochgestuften arithmetischen Typen sind für dieses Paar Operatoren definiert. 'int' ist bereits ein arithmetischer Typ. Promotion erzeugt nichts mit einem Rang größer als "int", es sei denn, es ändert den Typ nicht. 'int' ->' long long' ist keine gültige Werbung. – chris

+0

überprüfen Sie bitte meine aktualisierte Antwort, ich fürchte, dass Ihr Kommentar nicht widerspiegelt, was in Wirklichkeit passiert. "gefördert" mag nicht der richtige Ausdruck gewesen sein, aber "übliche arithmetische Konvertierungen" werden angewendet. –

-1

< Der Operator ist binär Daher könnte der Compiler Argumente in denselben Typ konvertieren und vergleichen.

Ansonsten min Funktion sollte etwas zurückgeben. Wie könnte der Compiler raten, welchen Typ er zurückgeben soll?

3

Wie in anderen Antworten, der Grund dafür ist, dass std::min die Typen der Argumente erfordert identisch, wenn Abzug durchgeführt werden soll, während < die üblichen arithmetischen Umwandlungen impliziert (§5.9/2), die sicherstellen wird, dass Die Typen werden in einen "gemeinsamen Nenner" umgewandelt. Beachten Sie, wie §13.12.06 Listen integrierten Operatoren als Kandidaten auf:

Für jedes Paar gefördert arithmetische Typen L und R existieren Bewerber Funktionen der Form

// […] 
LR operator<(L , R); 
// […] 

wo LR ist das Ergebnis der üblichen arithmetischen Umrechnungen zwischen Typen L und R.


Eigentlich sollte std::min der Lage sein, mit unterschiedlichen Typen zu behandeln. Das Folgende ist ein modernerer Ansatz:

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)...); 
} 

Demo.

+0

Ist es nicht möglich, 't' und' u' in 'common_type_t ' (für primitive Typen) zu konvertieren? Nun, es wird in einigen Fällen keine Kopie machen, wie es der obige Code tut: das kann jedoch mit etwas mehr Aufwand behoben werden. – Yakk

+0

@Yakk Ich habe etwas anderes versucht. Es kann jedoch auch einen 'Operator <' geben, der verschiedene Klassentypen vergleicht. Dann, 'a Columbo

+0

@Yakk Ahhh, das ist alles nicht gut. – Columbo