2015-08-11 13 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); 

--- 

Grazie a chris commento in function overloading post Template detrazione argomento non tiene conversioni in considerazione. Un parametro modello non può corrispondere a due tipiPerché meno di un operatore accetta diversi tipi di parametri mentre std :: min no?

Quindi std::min fallire.

Perché < funzionerebbe?

+3

Perché * fa * tiene conto delle conversioni. – molbdnilo

risposta

7

Perché lo < integrato si applica Numeric promotions e la deduzione argomento modello non lo fa.

+1

Potresti fornire un riferimento specifico a '<'? Ho capito "promozioni", ma non riesco a scoprire perché "<" è adatto a questa "promozione". – Kamel

+1

@Kamel È il caso di tutti gli operatori aritmetici incorporati ([collegamento] (http://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversions)). – Quentin

+0

Ho letto il documento di Java per imparare come usare il suo SDK, mentre leggevo il documento di C++ per imparare come il suo compilatore ha eseguito l'hacking per eseguire il codice. – Kamel

2

È perché std::min è una funzione di modello.

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

quindi ha bisogno gli argomenti per avere lo stesso tipo, ma se si utilizza (a<b), così a potrebbe implicitamente convertito in un long long

-1

tipi primitivi non sovraccaricare gli operatori, in modo vengono applicate le normali conversioni aritmetiche e l'int viene convertito in long long e lo "<" ha un significato valido.

Non si può nemmeno sovraccaricare gli operatori per i tipi primitivi: https://isocpp.org/wiki/faq/intrinsic-types#intrinsics-and-operator-overloading

esempio per dimostrare che il vostro int è promosso a long long

// 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; 
} 

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

Per la operatori binari (eccetto i turni), se gli operandi promossi hanno diff tipi erenti, serie aggiuntiva di conversioni implicite viene applicata , noto come conversioni aritmetiche abituali con l'obiettivo di produrre il tipo comune (accessibile anche tramite il tipo std :: common_type tratto)

+0

Ogni coppia di tipi aritmetici promossi dispone di operatori definiti per quella coppia. 'int' è già un tipo aritmetico promosso. La promozione non produce nulla con un valore superiore a 'int' a meno che non cambi il tipo. 'int' ->' long long' non è una promozione valida. – chris

+0

per favore controlla la mia risposta aggiornata, temo che il tuo commento non rifletta quello che in realtà sta accadendo. "promosso" potrebbe non essere stato il termine giusto, ma vengono applicate le "normali conversioni aritmetiche". –

-1

L'operatore < è binario , quindi il compilatore può convertire gli argomenti nello stesso tipo e confrontarli.

Altrimenti la funzione min dovrebbe restituire qualcosa. In che modo il compilatore può indovinare quale tipo dovrebbe restituire?

3

Come spiegato in altre risposte, il motivo è che std::min richiede che i tipi degli argomenti siano identici se si deve eseguire la detrazione, mentre < implica le normali conversioni aritmetiche (§5.9/2), che assicureranno che i tipi vengono convertiti in un "denominatore comune". Nota come §13.6/12 liste up operatori built-in come candidati:

Per ogni coppia di tipi aritmetici promosse L e R, esistono Funzioni candidato della forma

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

dove LR è il risultato delle solite conversioni aritmetiche tra tipi L e R.


realtà, std::min dovrebbe essere in grado di gestire tipi distinti. Il seguente è un approccio più moderno:

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

Non è probabile che 't '(per i tipi primitivi)? Bene, non farà una copia in alcuni casi come farà il tuo codice sopra: che, tuttavia, può essere riparato con un po 'più di sforzo. – Yakk

+0

@Yakk Ho provato qualcos'altro. Tuttavia, potrebbe esistere un 'operatore <' che mette a confronto tipi di classi distinti. Quindi, 'a Columbo

+0

@Yakk Ahhh, non va tutto bene. – Columbo

Problemi correlati