C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Temporäres Objekt für Funktionsparamete r mit const T*

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Marcel Müller
Guest





PostPosted: Sun May 20, 2007 12:18 am    Post subject: Temporäres Objekt für Funktionsparamete r mit const T* Reply with quote



Hallo,

ich habe folgende Situation:

struct MyArgs
{ //...
};

void foo(const MyArgs* param)
{
}

void bar(const MyArgs& param)
{ foo(&param); // geht
}

int main()
{
foo(&MyArgs()); // geht nicht, Compilerfehler
bar(MyArgs());
foo(&(const MyArgs&)MyArgs()); // geht

return 0;
}

Leider compiliert das nicht:

test.cpp(9:7) : error EDC3058: Operand of "&" operator must be an lvalue.

Schön und gut, aber warum geht der indirekte Aufruf über bar() dann
fehlerfrei. Soweit ich weiß darf man jederzeit konstante Referenzen auf
temporäre Objekte übergeben und sogar innerhalb eines Blocks halten. Und
man darf mit & einen Pointer auf ein konstantes Objekt aus einer
konstanten Referenz machen. Warum geht das nicht in einem Rutsch?

Es scheint wohl auch vom Compiler abzuhängen. Gcc bringt zumindest nur
eine Warnung. Das andere war icc (IBM).


Hintergrund: ich wollte das für den Aufruf von Callback-Funktionen
(Events) verwenden, um die nötigen EventArgs-Strukturen in einem
Einzeiler zu basteln.
Und den Funktionsparameter der Events traue ich mich nicht auf eine
Referenz zu ändern, da der ganze Kram für das Backend auf void* und
zurück gecastet wird. Dadurch ist die zugrundeliegende Implementierung
kein Template und damit das Executable deutlich kleiner. Eine Cast von
(T*) nach (void*) und wieder nach (T*) ist ja garantiert. Und (void
(*callback)(T*)) nach (void (*callback)(void*)) und zurück geht
üblicherweise auch gut.
Aber mit Referenzen müsste das heißen (void (*callback)(T&)) nach (void
(*callback)(void&)), was natürlich Blödsinn ist. Und von (void
(*callback)(T&)) nach (void (*callback)(void*)) zu casten, ist mir
endgültig zu heiß, obwohl ich bisher keine Implementierung kenne, bei
der der tatsächliche, technische Aufruf mit einer Referenz sich von dem
mit einem Pointer unterscheidet.


Marcel
Back to top
James Kanze
Guest





PostPosted: Mon May 21, 2007 2:07 pm    Post subject: Re: Temporäres Objekt für Funktionsparameter mit const T* Reply with quote



On May 19, 9:18 pm, Marcel Müller <news.5.ma...@spamgourmet.org>
wrote:

Quote:
ich habe folgende Situation:

struct MyArgs
{ //...

};

void foo(const MyArgs* param)
{
}

void bar(const MyArgs& param)
{ foo(&param); // geht
}

int main()
{
foo(&MyArgs()); // geht nicht, Compilerfehler

Genau. In Wörten der Norm ist MyArgs() kein lvalue.

Quote:
bar(MyArgs());
foo(&(const MyArgs&)MyArgs()); // geht

return 0;
}

Leider compiliert das nicht:

test.cpp(9:7) : error EDC3058: Operand of "&" operator must be an lvalue.

Schön und gut, aber warum geht der indirekte Aufruf über bar() dann
fehlerfrei.

Weil der Parameter von bar ein lvalue ist.

Quote:
Soweit ich weiß darf man jederzeit konstante Referenzen auf
temporäre Objekte übergeben und sogar innerhalb eines Blocks halten. Und
man darf mit & einen Pointer auf ein konstantes Objekt aus einer
konstanten Referenz machen. Warum geht das nicht in einem Rutsch?

Weil es verboten ist:-).

Die Grundregeln stammen aus C, wo du eigentlich nie die Adresse
einen Temporär bekommen kannst. Referenzen wurden in C++
eingefügt u.a. um überladene Operatore zu unterstützen, ohne zu
viele tiefen Kopien zu verlangen. Ein operator+ aber, worauf du
keinen Temporär als Parameter übergeben könnte, wäre nicht sehr
geschickt; also hat man erlaubt, Referenzen mit Temporären zu
initialisieren. Danach hat man bemerkt, dass es wohl zu
gefährlich ist, und hat es auf Referenzen an const beschränkt.
Nie aber hat man es für nötig gefühlt, diese Freiheit auch auf
Zeiger ausdehnen zu lassen. Der Grund des Unterschieds ist also
rein historisch.

Quote:
Es scheint wohl auch vom Compiler abzuhängen. Gcc bringt zumindest nur
eine Warnung. Das andere war icc (IBM).

Von der Sprache her ist es absolut verboten.

Wenn es um den eingebauten Operator geht. Im Sonderfall kannst
du der Operator& überladen. Dann gilt es als einen
Funktionsaufruf, was auf einem Temporär erlaubt ist. Also:

struct MyArgs
{
// ...
MyArgs const* operator&() { return this ; }
} ;

Ich würde aber so was nur in ganz besonderen Fällen benutzen,
wenn überhaupt.

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
Stefan Reuther
Guest





PostPosted: Mon May 21, 2007 3:23 pm    Post subject: Re: Temporäres Objekt für Funktionspara meter mit const T* Reply with quote



Marcel Müller wrote:
Quote:
void foo(const MyArgs* param)
void bar(const MyArgs& param)
[...]
foo(&MyArgs()); // geht nicht, Compilerfehler
bar(MyArgs());
foo(&(const MyArgs&)MyArgs()); // geht
[...]
Leider compiliert das nicht:

test.cpp(9:7) : error EDC3058: Operand of "&" operator must be an lvalue.

Schön und gut, aber warum geht der indirekte Aufruf über bar() dann
fehlerfrei. Soweit ich weiß darf man jederzeit konstante Referenzen auf
temporäre Objekte übergeben und sogar innerhalb eines Blocks halten. Und
man darf mit & einen Pointer auf ein konstantes Objekt aus einer
konstanten Referenz machen. Warum geht das nicht in einem Rutsch?

"Ist halt so". Wenn du es in einem Rutsch haben willst, verpasse der
Klasse 'MyArgs' eine Funktion, die den this-Pointer rausrückt. Wenn du
es ganz schön haben willst, nenne diese Funktion 'operator&':

struct MyArgs {
const MyArgs* operator&() const { return this; }
MyArgs();
};
void foo(const MyArgs* param);
void bar(const MyArgs& param);
void x() {
foo(&MyArgs()); // geht jetzt
bar(MyArgs());
foo(&(const MyArgs&)MyArgs()); // geht
}

Quote:
Und den Funktionsparameter der Events traue ich mich nicht auf eine
Referenz zu ändern, da der ganze Kram für das Backend auf void* und
zurück gecastet wird. Dadurch ist die zugrundeliegende Implementierung
kein Template und damit das Executable deutlich kleiner. Eine Cast von
(T*) nach (void*) und wieder nach (T*) ist ja garantiert. Und (void
(*callback)(T*)) nach (void (*callback)(void*)) und zurück geht
üblicherweise auch gut.

Da kannst du immer noch einen Wrapper drumbasteln, der aus den
Referenzen Zeiger macht und umgekehrt (eben sowas wie deine Funktion
'bar'). Als inline-Template o.ä. sollte das nichtmal Code generieren.


Stefan
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.