2014-02-23 10 views
15

Vorgegebene Typen A,B, ich bin besorgt mit der genauen Definition von std::common_type<A,B>, abgesehen von der Variadic Fall std::common_type<A...> für beliebige Typen A.... So lassensollte std :: common_type std :: zerfallen?

using T = decltype(true ? std::declval<A>() : std::declval<B>()); 
using C = std::common_type<A,B>; 

nun nach einer Reihe von Quellen, ich habe die folgenden Beziehungen (Überspringen typename der Kürze halber) gefunden:

  • cppreference.com: C::type = std::decay<T>::type

  • cplusplus.com: C::type = T

  • GCC 4.8.1 <type_traits> implementierung n: C::type = std::decay<T>::type wenn T gültig ist, sonst C kein ::type Mitglied enthält ("SFINAE freundlich")

  • Clang 3.3 <type_traits> Umsetzung: C::type = std::remove_reference<T>::type

Ich finde die "SFINAE freundliche" Version von GCC ein kleines Detail, während std::remove_reference und std::decay praktisch nur in integrierten Arrays und Funktionen, plus cv-Qualifikation unterscheiden, für die ich wieder nicht viel betroffen bin. Also meine Frage ist

Sollte es decay<T>::type oder nur T sein? Was ist der Grund für die Verwendung von decay<T>::type? Ist es nur ungefähr das Ergebnis A() + B() darzustellen, z.B. für arithmetische Ausdrücke?

Zum Beispiel eines wenig experimentiert, habe ich festgestellt, dass im Fall der „just T“ Definition, wir

common_type<int&,int&> = int& 
common_type<int&,long&> = long 

haben, ist, eine L-Wert Referenz beibehalten wird, wenn Typen gleich sind . Dies spiegelt die Tatsache wider, dass

int a, b; 
(true ? a : b) = 0; 

gültig ist, während

int a; 
long b; 
(true ? a : b) = 0; 

nicht. Diese Semantik von "Zuweisung zulassen, wenn Typen gleich sind" ist genau das, was ich in einer Anwendung benötige, und ich glaube, dass common_type und decay zwei unabhängige Schritte sein sollten. Soll ich nur meine eigenen Definitionen verwenden?

+0

'' und remove_reference' decay' auch für Referenztypen in der CV-Qualifikation unterscheiden hinzuzufügen ergibt; 'std :: declval ' gibt eine rvalue-Referenz zurück. – dyp

+0

'T' ist alt (C++ 11),' Zerfall 'ist neu (C++ 1y), es ist wahrscheinlich ein Defekt im Zusammenhang damit. Lass mich sehen .. – dyp

+0

@dyp Ja, ich war nicht so vorsichtig dort, deshalb schrieb ich "praktisch", ich werde reparieren. – iavr

Antwort

12

sollte std :: common_type verwenden std :: zerfallen?

Ja, siehe Library Working Group Defect #2141.

Kurzversion (lange Version, siehe Link oben):

  • declval<A>() gibt ein A&&

  • common_type über declval angegeben, n3337:

    template <class T, class U> 
    struct common_type<T, U> { 
        typedef decltype(true ? declval<T>() : declval<U>()) type; 
    }; 
    
  • common_type<int, int>::type daher Ausbeuten int&&, die Unerwartete wird

  • vorgeschlagenen Auflösung decay

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

+1

Hmm ... das zeigt in der Tat, wie wir "Verfall" benutzt haben, also beantwortet es die Frage, vielen Dank. Schade, aber ich muss jetzt meine eigenen Definitionen verwenden ... Ja, '' sollte 'int' und nicht' int && 'geben, aber' 'sollte' int & 'für mich geben. Daher sollten nur zusätzliche '&&' hinzugefügt durch 'declval' entfernt werden. – iavr

+0

@iavr Die Diskussion auf der LWG-Seite enthält * "Benutzer von' common_type' erwarten nicht, dass ein Referenztyp als Ergebnis erhalten wird "* Nicht sicher, wer * die Benutzer * sind. – dyp

+0

Nun, ich bin mir nicht sicher :-) – iavr

Verwandte Themen