simples decltype



  • namespace my {
        typedef decltype( nullptr - nullptr ) ptrdiff_t;
    }
    

    sollte doch funktionieren, oder?


  • Mod

    Geht nicht mit nullptr . Denn nullptr ist eben kein erlaubter Typ für diesen Ausdruck - weder Zeiger noch Enumeration noch arithmetisch.
    Es würde jedoch mit (char*)0 - (char*)0 gehen

    [expr.add]/8 schrieb:

    If two pointers point to the same object or both point one past the end of the same array or both are null, and the two pointers are subtracted, the result compares equal to the value 0 **converted to the type
    std::ptrdiff_t **.

    Demo


  • Mod

    Geht nicht. nullptr ist vom Typ nullptr_t. Dieser Typ ist zwar in sämtliche Zeigertypen konvertierbar, ist aber selber kein Zeiger. Insbesondere gibt es keinen doppelseitigen Minus-Operator für nullptr_t (und auch sonst keine anderen Operatoren, die mir gerade einfallen).

    edit: Zu langsam.


  • Mod

    Wozu überhaupt das Ganze? Für sowas ist <cstddef> da.



  • God damnit. Danke Euch beiden. static_cast< char * >( nullptr ) - static_cast< char * >( nullptr ) it is. Ist halt hässlich.

    @camper: das ist mir schon klar ... rumspielen & learning by doing.


  • Mod

    Keine Ahnung was der static_cast da soll ( (char*) wird hier per Definition das gleiche Verhalten wie ein static_cast haben). Oder nullptr . Wird hier nicht helfen.



  • Arcoth schrieb:

    Keine Ahnung was der static_cast da soll ( (char*) wird hier per Definition das gleiche Verhalten wie ein static_cast haben). [...]

    Schrabenzieher statt Holzhammer?

    Arcoth schrieb:

    [...] Oder nullptr . Wird hier nicht helfen.

    Mir ist nicht klar, was Du damit ausdrücken möchtest?

    typedef decltype( sizeof nullptr ) size_t; darf ich aber schon, gell?


  • Mod

    Du beschwerst dich über die Hässlichkeit eines Ausdrucks der deutlich kürzer und lesbarer geschrieben werden kann? 🙄

    typedef decltype( sizeof nullptr ) size_t; darf ich aber schon, gell?

    ... ja, oder einfach sizeof 0 , oder using namespace std::support_literals; und 0z mit C++17 (voraussichtlich). Hast du einen nullptr Fetisch?



  • Arcoth schrieb:

    Du beschwerst dich über die Hässlichkeit eines Ausdrucks der deutlich kürzer und lesbarer geschrieben werden kann? 🙄

    Jo. Hab einen seltsamen Geschmack, ich weiß.

    Arcoth schrieb:

    Swordfish schrieb:

    typedef decltype( sizeof nullptr ) size_t; darf ich aber schon, gell?

    ... ja, oder einfach sizeof 0 , oder [...]

    Sorry, aber ich hab keine Lust zu suchen und Du weißt es wahrscheinlich sowieso: Wo steht sizeof int == sizeof std::size_t ?

    Arcoth schrieb:

    Hast du einen nullptr Fetisch?

    Weiß nicht. Vielleicht.


  • Mod

    Swordfish schrieb:

    Sorry, aber ich hab keine Lust zu suchen und Du weißt es wahrscheinlich sowieso: Wo steht sizeof int == sizeof std::size_t ?

    Schlecht geschlafen?


  • Mod

    Wenn's unbedingt eine Pointersubtraktion sein soll und nullptr_t drin vorkommen soll, man aber nicht casten möchte:

    decltype(new nullptr_t - new nullptr_t);
    

    😃

    PS: Wie erstelle ich eigentlich einen temporären Pointer ohne new? Es ist irgendwie peinlich, aber ich komme nicht auf die passende Syntax.



  • Arcoth schrieb:

    Swordfish schrieb:

    Sorry, aber ich hab keine Lust zu suchen und Du weißt es wahrscheinlich sowieso: Wo steht sizeof int == sizeof std::size_t ?

    Schlecht geschlafen?

    Ne, warum? Wenn Du vermutest, daß ich evtl. auf Leitungen rumsteh' dann gib mir doch bitte einen Pointer (<-pun intended) in welche Richtung ich mich drehen soll.

    SeppJ schrieb:

    Wenn's unbedingt eine Pointersubtraktion sein soll und nullptr_t drin vorkommen soll, man aber nicht casten möchte:

    decltype(new nullptr_t - new nullptr_t);
    

    😃

    jaja, passt schon 🙄

    SeppJ schrieb:

    PS: Wie erstelle ich eigentlich einen temporären Pointer ohne new? Es ist irgendwie peinlich, aber ich komme nicht auf die passende Syntax.

    garnicht? Die Adresse eines Temporaries darfst nicht nehmen?


  • Mod

    Swordfish schrieb:

    garnicht? Die Adresse eines Temporaries darfst nicht nehmen?

    Ich meine nicht die Adresse eines Temporaries, sondern ein temporäres Pointerobjekt. À la

    int (5);
    


  • Naja. (int*)(42) ist ein cast. Ist der ausgewertete Ausdruck ein temporary?


  • Mod

    Swordfish schrieb:

    Naja. (int*)(42) ist ein cast. Ist der ausgewertete Ausdruck ein temporary?

    Der ist zwar temporary, aber nicht in dem Sinne, den ich meine. Das hier will ich machen können:

    void foo(int);
    void bar(int*);
    
    int main()
    {
      foo(int()); // Kein Problem, temporärer int, value initialized
      bar(???);   // Wie temporären int* (value initialized) erzeugen?
    }
    

    Denn dann könntest du deinen ptrdiff_t mittels decltype(??? - ???) bekommen, ganz ohne Cast, nullptr oder new.

    Das muss doch irgendwie gehen, aber ich komm nicht drauf. Ich sehe schon, dass ich mir ganz dumm vorkommen werde, wenn gleich Arcoth oder camper mit der Lösung kommen 🙂

    edit: So langsam glaube ich, das geht gar nicht. Nach genügend Standardlektüre komme ich zu dem Schluss, dass "int*" ein elaborated type specifier ist. Aber als Typangabe für value initialization verlangt nach einem simple type specifier. Man müsste sich also vorher so etwas wie ein typedef auf int* machen, denn ein typedef gilt wieder als simple type specifier.



  • SeppJ schrieb:

    Man müsste sich also vorher so etwas wie ein typedef auf int* machen, denn ein typedef gilt wieder als simple type specifier.

    Das wär mein erster Tip gewesen. Plan B:

    template< typename T >
    T* get_ptr() { T t; return &t; }
    

    ... dereferenzieren will man das Ding ja sowieso nicht.

    //edit: "value initialized" ... ne, ich glaub das wird nix.
    //edihit: Nachdem unsere Standard-Cracks wohl schlafen geh' ich damit mal Leute auf SO ärgern ... http://stackoverflow.com/questions/28205578/how-to-create-a-temporary-value-initialized-t-in-standard-c


  • Mod

    bar(decltype(new int)());
    

    ist technisch gesehen nat. trotzdem kein temporäres Objekt. Dafür müsste bar eine Referenz nehmen.



  • Yay! Kauf' ich!

    //naja ... bis zur Kopie ists doch temporary. Vieleicht recht Sepp das ja schon 😉


  • Mod

    Ne, warum? Wenn Du vermutest, daß ich evtl. auf Leitungen rumsteh' dann gib mir doch bitte einen Pointer (<-pun intended) in welche Richtung ich mich drehen soll.

    Wen interessiert der Wert von sizeof blablub wenn du lediglich den Typ des Ausdrucks haben willst? 😕

    @SeppJ: Mit Zeigersyntax geht es nicht [expr.type.conv]/1:

    A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list.

    simple-type-specifier sind entweder decltype(..) (wie von camper ausgenutzt), die keywords für Typen ( int , auto , usw.) oder qualified-ids.


  • Mod

    Swordfish schrieb:

    Yay! Kauf' ich!

    //naja ... bis zur Kopie ists doch temporary. Vieleicht recht Sepp das ja schon 😉

    Skalare rvalues sind keine Objekte. Das temporäre Objekt entsteht erst, wenn an die Referenz gebunden werden soll. Bei Klassen ist das anders.


Anmelden zum Antworten