Decltype Deklaration



  • Kurze Frage:

    Kann mir jemand sagen, was folgende Deklaration zu bedeuten hat?

    template<class T, class U> decltype((*(T*)0)+(*(U*)0)) add(T t, U u)
    

    Es handelt sich um einen duch VS2010 unterstützten C++0x Code. Was decltype macht ist mir im allgemeinen klar, aber was hat ((T)0) zu bedeuteten?

    Danke im voraus.



  • Pointer to T-Pointer.



  • (T*)0 ist ein Zeiger auf T mit dem wert NULL.
    (T)0 ist das Objekt vom Typ T, was dort liegt (wobei auf Adresse 0 kein Objekt liegen darf).

    cout<<((T)0) oder sowas führt natürlich sofort zu einer Schutzverletzung. Aber im decltype wird ja nur der Typ gebastelt, da geht das mal.

    Der Code macht also nur

    template<class T, class U> decltype(T()+U()) add(T t, U u)
    

    , nur ein wenig besser, weil mein Code verlangt, daß T und U einen Standardkonstruktor haben.



  • Das soll das gleiche bewirken wie

    template <class T, class U>
    auto add(T t, U u) -> decltype(t + u);
    

    Aus irgendeinem Grund benutzt der Schreiber aber nicht t und u, sondern macht sich Variablen aus Nullzeigern.



  • Was macht "->" Operator da?



  • Dass ist nicht der Pfeil-Operator, sondern eine neue Form der Funktionsdeklaration in C++0x. Er wird benötigt, da der Compiler hiermit nicht klarkommt:

    template <class T, class U>
    decltype(t + u) add(T t, U u);
           ^
           +------------------------------------ Was sind "t" und "u"?
    

    Deshalb nun diese neue Syntax.



  • Alternativ wird es ein Template declval geben, mit dem man sich Werte/Objekte aus dem Nichts zaubern kann, zwecks Bauen eines Ausdrucks für decltype.

    #include <utility>
    ...
    using std::declval;
    ...
    decltype( declval<int>() + declval<double>() ) blah;
    

    @FrEEzE2046: Mit der auto...-> Syntax kann man Funktionen deklarieren/definieren. Nach -> kommt der Rückgabetyp, welcher sich so verzögern lässt. So ist dem Compiler auch bekannt, was t und u ist.



  • Danke für eure Antworten. Ich hatte leider noch keine Zeit mich intensiver einzulesen.

    Noch schnell die Frage:
    Wofür wird das std::forward im Body benötigt? Reicht nicht return t + u;?



  • FrEEzE2046 schrieb:

    Wofür wird das std::forward im Body benötigt? Reicht nicht return t + u;?

    Ich sehe in diesem Thread kein Beispiel mit std::forward. (!)

    std::forward ist eigentlich dazu da, die "ürsprüngliche value-ness" wieder herzustellen. Es gibt Lvalue- und Rvalue-Ausdrücke. Zusammen mit Rvalue-Referenzen und einer speziellen Typ-Deduktionsregel erlaubt C++0x sogenanntes "perfect forwarding". std::forward ist eine Hilfsfunktion dafür.

    void foo(int const&); // frisst lvalue-ausdrücke
    void foo(int     &&); // frisst non-const rvalue ausdrücke
    
    template <typename T>
    void forwardor(T && x)
    {
      foo( std::forward<T>(x) );
    }
    
    int main()
    {
      int i = 23;
      forwardor(i);   // ruft foo(int const&) auf, da T=int&
      forwardor(i+1); // ruft foo(int     &&) auf, da T=int
    }
    

    Die "value-ness" (L oder R) des Arguments bleibt in Form des Typ-Parameters T erhalten.

    kk


Anmelden zum Antworten