[C++] this und const

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

[C++] this und const

Beitrag von RustySpoon »

Hallo allerseits,

welchen Typ hat denn this innerhalb einer const-Methode? Intuitiv hätte ich auf T const* const getippt. Hier wird das auch genauso spezifiert.

Allerdings scheint der GCC stattdessen T const* anzunehmen, was man hier nachvollziehen kann.

Also, woher kommt diese Ungereimtheit?
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] this und const

Beitrag von CodingCat »

Offiziell ist this als (pure) R-Value spezifiziert, also die Adresse deines Objektes in Form eines temporären Wertes vom Typ T* in unqualifizierten oder const T* in const-qualifizierten Methoden.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

Re: [C++] this und const

Beitrag von RustySpoon »

Danke für die Antwort, erscheint mir soweit erstmal plausibel.

Du sagst "offiziell", ist es möglich, dass unterschiedliche Compiler das unterschiedlich handhaben? Bzw. ist das eventuell irgendwie eklig vom Kontext abhängig?

Worum es mir konkret geht ist Folgendes:

Code: Alles auswählen

inline variable_type watcher2(clause_type clause) const
{
    return static_cast<
                typename std::conditional<
                    std::is_const<typename std::remove_pointer<decltype(this)>::type>::value,
                    State const* const,
                    State* const>::type>(this)->inner_state()[clause].watcher2;
}
Das ist letztendlich einfach eine Realisierung des CRTP-Idioms. State ist die abgeleitete Klasse. Leider bekomm ich beim Kompilieren (GCC 4.7.1) immer folgenden Fehler (aus Gründen der Lesbarkeit etwas gekürzt):
error: static_cast from type 'const watcher_facet<walksat_state, ...>* const' to type 'std::conditional<false, const walksat_state* const, walksat_state* const>::type {aka walksat_state* const}' casts away qualifiers
watcher_facet ist die CRTP-Basisklasse, walksat_state die Abgeleitete.

std::is_const sollte meines Erachtens zu true evaluieren - tut es aber nicht.

Bastel ich dazu ein Minimalbeispiel funktioniert es. Scheinbar hab ich also nur Tomaten auf den Augen.

Any ideas?
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] this und const

Beitrag von CodingCat »

Läuft das Minimalbeispiel denn auch in deinem Compiler? Welchen Typ gibt decltype(this) bzw. typename std::remove_pointer<decltype(this)>::type bei dir denn im Kontext zurück?
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

Re: [C++] this und const

Beitrag von RustySpoon »

Japp, läuft bei mir auch tadellos.

Langsam bekomm ich Licht ins Dunkel und meine Verwirrungen.

Hier hab ich mal die einzelnen Typen aufgeschlüsselt. Erstmal ist festzuhalten: Du hast Recht, der this-Typ ist T const* innerhalb einer const-Methode.

Strange ist nun allerdings die oben genannte Fehlermeldung. Der Compiler scheint im Fall des Casts ja von const watcher_facet<walksat_state, ...>* const auszugehen. Rührt das daher, dass this R-Value ist?

Das eigentliche Problem kommt aber woanders her. Das Anwenden von std::remove_pointer bzw. Dereferenzieren von this führt dazu, dass sich der Typ von T const* (const) hin zu T verändert. Ich hatte da irgendwie nicht länger drüber nachgedacht und intuitiv T const angenommen. Diesbezüglich bitte ich auch noch um Aufklärung, so richtig ist der Groschen nämlich noch nicht gefallen.

Ist das Problem irgendwie angekommen? Vielen Dank für die Hilfe!

Edit: Gut, hab die letzte Frage mal rausredigiert, das war banal.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] this und const

Beitrag von CodingCat »

RustySpoon hat geschrieben:Hier hab ich mal die einzelnen Typen aufgeschlüsselt. Erstmal ist festzuhalten: Du hast Recht, der this-Typ ist T const* innerhalb einer const-Methode.
[...]
Das Anwenden von std::remove_pointer bzw. Dereferenzieren von this führt dazu, dass sich der Typ von T const* (const) hin zu T verändert. Ich hatte da irgendwie nicht länger drüber nachgedacht und intuitiv T const angenommen. Diesbezüglich bitte ich auch noch um Aufklärung, so richtig ist der Groschen nämlich noch nicht gefallen.
Achtung, typeid entfernt top-level Qualifizier und Referenzen. Nur weil da kein const ausgegeben wird, ist es noch lange nicht weg. Bis hin zu einem unqualifizierten T ändert sich da nämlich nichts. Für vernünftige Typausgabe kommst wohl um ein winziges Hilfstemplate nicht drumrum (auch gerade beim Beantworten deines Posts zum ersten Mal gebaut, warum hat die STL sowas nicht?!):

Code: Alles auswählen

template <class T> struct type_printer { static void print() { std::cout << typeid(T).name(); } };
template <class T> struct type_printer<T const> { static void print() { type_printer<T>::print(); std::cout << " const"; } };
template <class T> struct type_printer<T*> { static void print() { type_printer<T>::print(); std::cout << " *"; } };
template <class T> struct type_printer<T&> { static void print() { type_printer<T>::print(); std::cout << " &"; } };
Damit kommen wir zu folgendem vernünftigen Ergebnis:

Code: Alles auswählen

decltype(this): 
4baseI7derivedE const *
typename std::remove_pointer<decltype(this)>::type: 
4baseI7derivedE const
decltype(*this): 
4baseI7derivedE const &
typename std::conditional< std::is_const< typename std::remove_pointer<decltype(this)>::type>::value, Derived const* const, Derived* const>::type: 
7derived const * const
const method
Viel wichtiger wäre jetzt, dass du derlei Analyse mal in deinem Kontext durchführst (siehe Hilfsmakros im verlinkten Paste, um den Überblick über die Typzuordnung nicht zu verlieren).
RustySpoon hat geschrieben:Strange ist nun allerdings die oben genannte Fehlermeldung. Der Compiler scheint im Fall des Casts ja von const watcher_facet<walksat_state, ...>* const auszugehen. Rührt das daher, dass this R-Value ist?
Exakt, C++ nimmt es mit R-Values immer noch einigermaßen genau und erlaubt sinnigerweise keine Zuweisung zu temporären Objekten.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

Re: [C++] this und const

Beitrag von RustySpoon »

CodingCat hat geschrieben:Viel wichtiger wäre jetzt, dass du derlei Analyse mal in deinem Kontext durchführst (siehe Hilfsmakros im verlinkten Paste, um den Überblick über die Typzuordnung nicht zu verlieren).
Naja, nachdem du meine Gedanken jetzt entquirlt hast, hab ich mir einfach ein kleines std::is_const-like Hilfstemplate gebastelt, welches testet, ob der Basistyp eines Zeigers const-qualifiziert ist. Damit funktioniert erstmal alles super. Danke für die ausführlichen Erklärungen, hab so einiges dabei gelernt!

Btw.: Flattr-Buttons und 'ne Ideone-Integration im Forum wären irgendwie schön. Würde dem Kater/den Betreibern jetzt gern was Gutes tun... ;)
Antworten