[C++] g++ te kieskeurig?

Pagina: 1
Acties:
  • 270 views sinds 30-01-2008
  • Reageer

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Ziehier het volgende stukje code (Datum stelt een willekeurige klasse voor):

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Test.cpp

#include "Datum.h"

void test(Datum& d)
{   
}

int main()
{
    test(Datum());
    Datum temp;
    test(temp);
}


Als ik dit probeer te compileren, krijg ik de volgende error:

code:
1
2
3
Test.cpp: In function `int main()':
Test.cpp:11: could not convert `Datum()' to `Datum&'
Test.cpp:6: in passing argument 1 of `void test(Datum&)'


Nu is mijn vraag: waarom werkt die aanroep van test() op regel 13 wél en die op regel 11 niet?
Uiteindelijk gebeurt er achter de schermen toch bijna precies hetzelfde?

De MS VisualC++ 6.0 compiler klaagt hier trouwens helemaal niet over.
Ik vond het eerst wel leuk dat g++ al mijn slordigheidsfoutjes opmerkte,
die door VC door de vingers werden gezien.
Maar ik begrijp totaal niet waarom 'm hierover klaagt.

(g++ (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5) btw)

[ Voor 7% gewijzigd door DieterVDW op 30-12-2003 23:47 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Stroustrup hoofdstuk 5.5 :)

[edit]
Mocht je die niet op de plank hebben (be ashamed ;) ) hierbij het vitale stukje:
The initializer for a 'plain' T& must be an lvalue of type T. The initializer for a const T& need not be an lvalue or even be of type T. In such cases:
[1] first implicit type conversion is applied if necessary
[2] then, the resulting value is placed in a temporary variable of type T; and
[3] finally, this temporary variable is used as the valuee initializer
Ik neem aan dat je met wat nadenken zelf wel snapt waarom ;)

[ Voor 91% gewijzigd door curry684 op 30-12-2003 23:59 ]

Professionele website nodig?


  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Ik schaam mij :'(

Ik heb dat nu trouwens al een stuk of 10 keer gelezen en het dringt nog niet door... *zucht*
Btw waarom pakt MS VC het dan wel?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

DieterVDW schreef op 31 december 2003 @ 00:22:
Ik schaam mij :'(

Ik heb dat nu trouwens al een stuk of 10 keer gelezen en het dringt nog niet door... *zucht*
Btw waarom pakt MS VC het dan wel?
Omdat VC6 een rotcompiler is :)

VC7.0 en 7.1 slikken het ook zonder warnings trouwens, maar dat zijn mindere k*tcompilers dan 6.0 ;)

Als je ooit twijfelt aan een stukje C++, klik hier :Y)

edit:
Misschien trouwens leuke kanttekening dat ik met oisyn op IRC al 10 minuten aan het ruzieen ben over deze constructie, en we zijn het er een beetje over eens dat het 'verbod' nogal overbodig is, het kan namelijk best gewenst gedrag zijn wat je wilt. Het verbod is wsch gestoeld op dat het nutteloos en fout is in het enorme merendeel van de gevallen.

[ Voor 27% gewijzigd door curry684 op 31-12-2003 00:33 ]

Professionele website nodig?


  • xoror
  • Registratie: November 1999
  • Niet online
DieterVDW schreef op 31 december 2003 @ 00:22:
Ik schaam mij :'(

Ik heb dat nu trouwens al een stuk of 10 keer gelezen en het dringt nog niet door... *zucht*
Btw waarom pakt MS VC het dan wel?
je geeft aan line 11 een temp object mee. die zijn per definitie const. je funktie test accepteert een reference als argument, dat strookt niet met elkaar.

maak er void test(const Datum& d) van

Mitsubishi Warmtepomp uitlezen/besturen met een ESP32


  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Een verhelderende uitleg door curry684 over wat er nu precies gebeurt bij
zo'n constructie:

<Curry> kijk je geeft iets by-reference mee
<Curry> zodat je het kunt wijzigen
<Curry> echter, daar stop je een temporary in
<Curry> waarvan de wijzigingen nooit opgeslagen kunnen en zullen worden
<Curry> in vrijwel alle gevallen is dit het gevolg van een bug, denkfout of typfout
<DieterVDW> ja, maar dan is het gewoon extreem nutteloos
<Curry> als je er een const-reference van maakt mag het plots wel
<Curry> en is het ineens nuttig
<DieterVDW> dus g++ straft me puur af op de nutteloosheid van m'n code :D ?
<Curry> g++ niet zozeer als wel de C++ standaard
<Curry> waar vc++ zich hier dus niet aan houdt
<Curry> de nutteloosheid is dermate enorm dat het verboden is
<Curry> vergelijk het met 2 pointers vermenigvuldigen
<Curry> het kan theoretisch
<Curry> maar het slaat nergens op

Tnx Curry!

  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 99% gewijzigd door Eelis op 18-02-2015 19:55 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
curry684 schreef op 31 december 2003 @ 00:31:
edit:
Misschien trouwens leuke kanttekening dat ik met oisyn op IRC al 10 minuten aan het ruzieen ben over deze constructie, en we zijn het er een beetje over eens dat het 'verbod' nogal overbodig is, het kan namelijk best gewenst gedrag zijn wat je wilt. Het verbod is wsch gestoeld op dat het nutteloos en fout is in het enorme merendeel van de gevallen.
Inderdaad. Zo gebruik ik 'de rotcompiler' en het volgende vond ik wel makkelijk:
C++:
1
2
3
4
5
6
7
8
void f(ostream&)
{
}

int main()
{
    f(ofstream("...");
}

Maar g++ houdt daar dus niet van (en mijn 'rotcompiler' wel). Maar als het 9/10x een bug is, dan is het warning toch genoeg?

[ Voor 8% gewijzigd door Olaf van der Spek op 31-12-2003 14:45 ]


  • xoror
  • Registratie: November 1999
  • Niet online
Eelis schreef op 31 december 2003 @ 04:12:
[...]

Neen.
C++:
1
2
3
4
5
6
7
struct S {
  void m (); // niet const
};

void f () {
  S().m(); // nonconst methode aangeroepen op temporary
}
eh, leest mijn posting nog eens. ik had het over temp object die je als arg meegeeft aan een funktie. zie uitleg irc log boven

Mitsubishi Warmtepomp uitlezen/besturen met een ESP32


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

OlafvdSpek schreef op 31 december 2003 @ 14:28:

Maar g++ houdt daar dus niet van (en mijn 'rotcompiler' wel). Maar als het 9/10x een bug is, dan is het warning toch genoeg?
Eensch, zoals reeds aangegeven. Helaas was Bjarne het daar niet mee eens :) Het is zoals ik zei hetzelfde als pointers vermenigvuldigen: potentieel nuttig maar in principe nooit. Jouw construct kun je afvangen door een overload te maken die een const ofstream& accepteert. Tja :Y)

Misschien moeten we even op MSalters wachten voor officiele onderbouwing :P

Professionele website nodig?


  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 128% gewijzigd door Eelis op 18-02-2015 19:55 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
curry684 schreef op 31 december 2003 @ 15:39:
[...]

Eensch, zoals reeds aangegeven. Helaas was Bjarne het daar niet mee eens :) Het is zoals ik zei hetzelfde als pointers vermenigvuldigen: potentieel nuttig maar in principe nooit. Jouw construct kun je afvangen door een overload te maken die een const ofstream& accepteert. Tja :Y)

Misschien moeten we even op MSalters wachten voor officiele onderbouwing :P
Eh, kun je nog iets schrijven naar een const ostream& dan?

En wat is de potentie van het vermenigvuldigen van twee pointers dan?

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
OlafvdSpek schreef op 31 december 2003 @ 14:28:
[...]

Inderdaad. Zo gebruik ik 'de rotcompiler' en het volgende vond ik wel makkelijk:
C++:
1
2
3
4
5
6
7
8
void f(ostream&)
{
}

int main()
{
    f(ofstream("..."));
}

Maar g++ houdt daar dus niet van (en mijn 'rotcompiler' wel). Maar als het 9/10x een bug is, dan is het warning toch genoeg?
Sim-pel
C++:
1
2
3
4
5
6
7
8
void f(ostream&)
{
}

int main()
{
    f(ofstream("...").flush());
}

:)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
MSalters schreef op 01 januari 2004 @ 17:17:
Sim-pel
C++:
1
2
3
4
5
6
7
8
void f(ostream&)
{
}

int main()
{
    f(ofstream("...").flush());
}

:)
Inderdaad simpel, maar wel met een andere semantiek en alleen bruikbaar in specifieke situaties. En een IMO niet nette work-around.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

OlafvdSpek schreef op 31 december 2003 @ 17:59:
[...]

Eh, kun je nog iets schrijven naar een const ostream& dan?

En wat is de potentie van het vermenigvuldigen van twee pointers dan?
Zoals [rml]MSalters in "[ c++] Nonconst references initializeren ..."[/rml] het zo netjes uitdrukt: je moet met een workaround werken om de vieze construct te laten werken. C++ kent niet voor niets de const-cast, hoe lelijk die potentieel ook is: maar het feit dat je 'm expliciet gebruikt maakt duidelijk dat je een potentieel foute constructie omzeilt:
C++:
1
2
3
4
5
6
7
8
9
10
11
void f(const ostream& a) 
{ 
ostream& mysteam = const_cast<ostream&>(a);

...
} 

int main() 
{ 
    f(ofstream("..."); 
}

De echte nette workaround is natuurlijk idioot simpel:
C++:
1
2
3
4
5
6
7
8
9
10
void f(const ostream& a) 
{ 
...
} 

int main() 
{
    ofstream mystream("...");
    f(mystream); 
}

En pointers vermenigvuldigen kan ik me bijvoorbeeld iets bij voorstellen als je een simpele random-functie hebt die de this-pointer met een constante vermenigvuldigt om alle instances van een class een andere seed of id te geven. Ik zou het zelf zo ook niet doen, maar potentieel nuttig voor mensen met iets scheefs in hun hoofd :P

[ Voor 25% gewijzigd door curry684 op 01-01-2004 23:51 ]

Professionele website nodig?


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
curry684 schreef op 01 januari 2004 @ 23:48:
[...]

Zoals [rml]MSalters in "[ c++] Nonconst references initializeren ..."[/rml] het zo netjes uitdrukt: je moet met een workaround werken om de vieze construct te laten werken. C++ kent niet voor niets de const-cast, hoe lelijk die potentieel ook is: maar het feit dat je 'm expliciet gebruikt maakt duidelijk dat je een potentieel foute constructie omzeilt:
C++:
1
2
3
4
5
6
7
8
9
10
11
void f(const ostream& a) 
{ 
ostream& mysteam = const_cast<ostream&>(a);

...
} 

int main() 
{ 
    f(ofstream("..."); 
}

De echte nette workaround is natuurlijk idioot simpel:
C++:
1
2
3
4
5
6
7
8
9
10
void f(const ostream& a) 
{ 
...
} 

int main() 
{
    ofstream mystream("...");
    f(mystream); 
}

En pointers vermenigvuldigen kan ik me bijvoorbeeld iets bij voorstellen als je een simpele random-functie hebt die de this-pointer met een constante vermenigvuldigt om alle instances van een class een andere seed of id te geven. Ik zou het zelf zo ook niet doen, maar potentieel nuttig voor mensen met iets scheefs in hun hoofd :P
Maar de functie f is niet fout, dus om daar nou een const_cast in te zetten.
Die tweede work-around gebruik ik nu ook, maar ik blijf het een klein beetje jammer vinden dat het nodig is.
Jij had het over het vermenigvuldigen van twee pointers, niet over constant * pointer.

[ Voor 7% gewijzigd door Olaf van der Spek op 02-01-2004 00:07 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

OlafvdSpek schreef op 02 januari 2004 @ 00:06:
Jij had het over het vermenigvuldigen van twee pointers, niet over constant * pointer.
Tis allebei verboden ;)

Professionele website nodig?


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Weet ik, maar ik was erg nieuwsgiering naar de potentiele nuttigheid van de vermenigvuldiging van twee pointers.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
curry684 schreef op 01 januari 2004 @ 23:48:
En pointers vermenigvuldigen kan ik me bijvoorbeeld iets bij voorstellen als je een simpele random-functie hebt die de this-pointer met een constante vermenigvuldigt om alle instances van een class een andere seed of id te geven. Ik zou het zelf zo ook niet doen, maar potentieel nuttig voor mensen met iets scheefs in hun hoofd :P
Niet nuttig, want je verliest typisch significante bits. Omdat this pointers meestal aligned zijn, moet je voor een goede random seed delen door de alignment grootte. Dan vallen die laatste nullen er af. (8>

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1