const hinter Funktion
-
krümelkacker schrieb:
private und const sind Schl+sselwörter. Die Verwendung von Schlüsselwörter als "Makro-Namen" ist meines Wissens nach U.B.
Der Beitrag war nicht so wirklich ernst gemeint und bezog sich auf das Wegcasten von
const
.
-
> Der Beitrag war nicht so wirklich ernst gemeint
War schon klar.
> U.B. ? Mein Compiler schluckt den sche.... kommentarlos.
Ich sehe hier keinen Widerspruch.
-
Ein blödes const-Problem, das ich in letzter Zeit hatte, war folgendes: In einer Library gab es einige typedefs:
typedef __mpfr_struct mpfr_t[1]; typedef __mpfr_struct *mpfr_ptr;
Nun hatte ich in meiner Klasse folgendes
class Number { mpfr_t mpfr_number; public: //.... mpfr_ptr get_mpfr_number() //es muss ein Pointer zurückgegeben werden, da ein Array nicht zurückgegeben werden darf { return mpfr_number; } const mpfr_ptr get_mpfr_number() const //Compiler meckert: warning: type qualifiers ignored on function return type { return const_cast<const mpfr_ptr>(mpfr_number); //ohne gings nicht } }
Was war das Problem? const mpfr_ptr ist ein konstanter Pointer, der auf variablen Inhalt zeigt. Ich brauche aber einen variablen Pointer, der auf konstanten Inhalt zeigt. Das geht AFAIK nur mit const __mpfr_struct *, da __mpfr_struct * const, const mpfr_ptr sowie mpfr_ptr const alles konstante Pointer sind. Wer garantiert mir jetzt, dass der struct-Name nicht in der nächsten Version der Library geändert wird? In der Dokumentation wurden, soweit ersichtlich, nur die typedef-Namen gebraucht.
-
Du gibst einen konstanten Zeiger zurück. Du willst aber einen Zeiger auf ein konstantes Objekt zurückgaben:
typedef __mpfr_struct *mpfr_ptr; typedef __mpfr_struct const * const_mpfr_ptr; const_mpfr_ptr get_mpfr_number() const
-
Tachyon schrieb:
Du gibst einen konstanten Zeiger zurück. Du willst aber einen Zeiger auf ein konstantes Objekt zurückgaben:
typedef __mpfr_struct *mpfr_ptr; typedef __mpfr_struct const * const_mpfr_ptr; const_mpfr_ptr get_mpfr_number() const
Das habe ich doch schon gesagt. Ich war mir bloß unsicher, ob von der Library garantiert wird, dass sich der Name von __mpfr_struct nicht ändert.
-
wxSkip schrieb:
[...]Das habe ich doch schon gesagt. Ich war mir bloß unsicher, ob von der Library garantiert wird, dass sich der Name von __mpfr_struct nicht ändert.
Ich habe nicht zu ende gelesen, sorry. Selbst wenn sich der Name der Struktur ändern sollte: Der Änderungsaufwand würde sich ja nur auf den
typedef
beschränken. So schlimm sollte das also eigentlich nicht sein.
-
Tachyon schrieb:
wxSkip schrieb:
[...]Das habe ich doch schon gesagt. Ich war mir bloß unsicher, ob von der Library garantiert wird, dass sich der Name von __mpfr_struct nicht ändert.
Ich habe nicht zu ende gelesen, sorry. Selbst wenn sich der Name der Struktur ändern sollte: Der Änderungsaufwand würde sich ja nur auf den
typedef
beschränken. So schlimm sollte das also eigentlich nicht sein.Da hast du natürlich recht. Es kam mir auch mehr aufs Prinzip an (und die Syntax hat mich ein bisschen geärgert, weil ich erst eine Woche danach draufgekommen bin).
-
Man könnte natürlich auch mit type_traits den Zeigertypen bauen:
typedef remove_pointer<mpfr_ptr>::type const* const_mpfr_ptr;
oder ohne Abhängigkeit von C++0x/Boost/TR1:
template<class T> struct constify_pointee; template<class T> struct constify_pointee<T*> { typedef T const* type; }; template<class T> struct constify_pointee<T*const> { typedef T const*const type; }; ... typedef constify_pointee<mpfr_ptr>::type const_mpfr_ptr;
Wenn die Bibliothek (GNU MPFR?) so einen typedef nicht anbietet, dann wird "const" dort wahrscheinlich auch kaum benutzt. Dann würde dir ein solcher Zeiger natürlich nicht viel bringen ... es sei denn, du magst const_cast vor Funktionsaufrufen anwenden...
-
krümelkacker schrieb:
Wenn die Bibliothek (GNU MPFR?) so einen typedef nicht anbietet, dann wird "const" dort wahrscheinlich auch kaum benutzt. Dann würde dir ein solcher Zeiger natürlich nicht viel bringen ... es sei denn, du magst const_cast vor Funktionsaufrufen anwenden...
Ja, es ist MPFR. In der Doku steht zwar nie was von const-Argumenten, ich kann diese const-Pointer aber problemlos anwenden (keine Compilerwarnung bei höchster Warnungsstufe), auch in const-Funktionen.
Natürlich übergebe ich als Element, das verändert wird, auch keinen const-Pointer.
-
Hm... habe das gerade mal getestet und ein komisches Ergebnis bekommen...
#include <iostream> using namespace std; class test { //... }; typedef test my_t[1]; typedef test *my_ptr; typedef const test *const_my_ptr; typedef test *const my_const_ptr; class abc { my_t tmp; public: my_ptr gettmp(){cout << "normal function called\n"; return tmp;} const_my_ptr gettmp() const{cout << "const function called\n"; return tmp;} }; void func(const my_t in) { cout << "const my_t in\n"; } void func(my_t in) { cout << "my_t in\n"; } template<typename T>T const &get_obj(T const &in){return in;} template<typename T> T &get_obj(T &in){return in;} int main() { abc val1; const abc val2 = abc(); func(val1.gettmp()); //output: "normal function called\n my_t in\n" func(get_obj(val1).gettmp()); //output: "normal function called\n my_t in\n" func(val2.gettmp()); //output: "const function called\n const my_t in\n" func(get_obj(val2).gettmp()); //output: "const function called\n const my_t in\n" func(abc().gettmp()); //output: "normal function called\n my_t in\n" !!!??? func(get_obj(abc()).gettmp()); //output: "const function called\n const my_t in\n" }
Macht man die const-Version von func() weg, gibt's Konvertierungs-Errors.
-
wxSkip schrieb:
Hm... habe das gerade mal getestet und ein komisches Ergebnis bekommen...
[...]
Macht man die const-Version von func() weg, gibt's Konvertierungs-Errors.Das ist nicht verwunderlich. Du kannst einen Zeiger vom Typ "const T*" nicht ohne const_cast nach "T*" konvertieren. Und das ist auch genau das, was ich meinte. Wenn Du da jetzt ein const dranfriemelst, kannst Du mit einem solchen Zeiger nichts mehr anfangen, da all die Bibliotheksfunktionen einen non-const Zeiger haben wollen, obwohl sie nicht alle das Objekt verändern. Du spührst hier den "viralen Effekt" von const.
Lösung 1: Vergiss const
Lösung 2: Bau Dir eine Zwischen-Schicht zwischen Deinem Programm und MPFR. Im einfachsten Fall sind das Wrapper-Funktionen, die ggf const_cast intern benutzen und die Aufrufe weiter an MPFR leiten.Beipsiel:
int bloede_c_funktion_ohne_const(int*x) { printf("%d\n",*x); // *x wird nicht geändert return *x + 3; // *x wird nicht geändert } inline int const_korrekter_wrapper(const int*x) { return bloede_c_funktion_ohne_const(const_cast<int*>(x)); }
kk
-
Das mit den Konvertierungs-Errors war nur eine Anmerkung. Mit dem verwunderlichen meinte ich, dass abc().gettmp() nicht die const-Version von gettmp() aufruft, obwohl abc() ein rvalue ist. Ich habe ja keine Probleme mit MPFR, daher benutzt die Bibliothek anscheinend const mpfr_t-Parameter, auch wenn davon in der Doku nicht die Rede ist.