2015-05-06 12 views
5

Wenn ich in einen Code-Schnipsel suche eine mögliche Implementierung von std::common_typeRückgabetyp von decltype wenn ternären angewandt (? :) Ausdruck

template <class ...T> struct common_type; 

template <class T> 
struct common_type<T> { 
    typedef decay_t<T> type; 
}; 

template <class T, class U> 
struct common_type<T, U> { 
    typedef decay_t<decltype(true ? declval<T>() : declval<U>())> type; 
}; 

template <class T, class U, class... V> 
struct common_type<T, U, V...> { 
    typedef common_type_t<common_type_t<T, U>, V...> type; 
}; 

Der Teil, wie eine gemeinsame Art für zwei Template-Argument erhalten macht mich confused.Es ist eine Verwendung von ternären Operator mit declype.

Wie bekannt ist, ob der zweite oder dritte Operand zurückgegeben wird, wird durch den Wert des ersten Operanden entschieden. In diesem Snippet lautet der erste Operand wahr, was bedeutet, dass der Rückgabewert von Ausdruck immer declval<T>() ist. Wenn es ist, was ich dachte, die keinen Sinn machen ... Deshalb habe ich den folgenden Test versucht

int iii = 2; 
float fff = 3.3; 
std::cout << typeid(decltype(false? std::move(iii):std::move(fff))).name() << std::endl; 
std::cout << typeid(decltype(std::move(iii))).name() << std::endl; 
std::cout << typeid(decltype(false ? iii : fff)).name() << std::endl; 
std::cout << typeid(decltype(true ? iii : fff)).name() << std::endl; 

// [02:23:37][[email protected]++_test]$ g++ -std=c++14 -g common_type.cpp 
// output 
// f 
// i 
// f 
// f 

mit dem laufenden Ergebnis Vergleicht man das Ergebnis, was, obwohl ich sein sollte wie folgt

int iii = 2; 
float fff = 3.3; 
std::cout << typeid(decltype(false ? iii : fff)).name() << std::endl; // should return f; 
std::cout << typeid(decltype(true ? iii : fff)).name() << std::endl; // should return i; 

Wer kann erklären, warum das Laufergebnis anders ist?

Mit anderen Worten, was ist das Ergebnis von decltype, wenn es auf einen ternären Ausdruck angewendet wird?

+4

In Ihrem Beispielcode wird der Wert in 'iii' in den Datentyp 'float' konvertiert, da das Ergebnis von ternary der Typ" breiteste "ist. – jxh

+0

Ich dachte, selbst wenn der zweite und der dritte Operand nicht vom selben Typ sind, wird implizit keine Konvertierung stattfinden. Weil ** (wahr? 1: 2,0) ** 1 anstelle von 1.0 zurückgibt. Laut der wundervollen Erklärung von @ T.C. habe ich verstanden, worauf es ankommt. Danke trotzdem. – ryu

Antwort

3

Der Typ eines Ausdrucks ist eine Kompilierzeit Eigenschaft. Der Wert des ersten Operanden in einem Bedingungsausdruck (und daher der ausgewählte Zweig) ist im Allgemeinen eine Laufzeit Sache, so dass es den Typ des Ausdrucks möglicherweise nicht beeinflussen kann.

Stattdessen wird ein komplizierter Satz von Regeln (mehr als eine Standardseite, von denen die meisten in this answer zitiert wurden) verwendet, um zu bestimmen, was der "gemeinsame Typ" des zweiten und dritten Operanden ist und der Bedingungsausdruck ist von diesem Typ. std::common_type nutzt lediglich die bestehenden Regeln in der Kernsprache.

Verwandte Themen