Article View: comp.std.c++
Article #3206Re: Explicit constructor call vs Temporaries
From: James Kanze US/ESC 60/3/141 #407...
Date: Fri, 02 Feb 1996 15:49
Date: Fri, 02 Feb 1996 15:49
130 lines
4659 bytes
4659 bytes
In article <4eq5p2$fpu@fsuj01.rz.uni-jena.de>
mkt@isun04.inf.uni-jena.de (Tilo Koerbs) writes:
|> About the error message in this posted code:
|> > class T {
|> > T();
|> > ~T();
|> > }
|> >
|> > class X {
|> > X();
|> > ~X();
|> > f(T& t);
|> > }
|> >
|> > int main() {
|> > X x;
|> > x.f(T()); // Compiler complained on this line
|> > }
|> The 'temporary' (it is an UNNAMED) T()-object is NOT const!
|> Consider:
|> class T {
|> public:
|> T();
|> ~T();
|> void nonConstFct() {}
|> };
|> int main() {
|> T().nonConstFct(); // Allowed!!!
|> }
|> And so the compiler should have no problem with this code!
|> I compiled it without any problem!
Except that the rules forbid binding a temporary to a non-const
reference, independantly of whether the temporary is const or not.
(See section 8.5.3 in the draft standard: "If the initializer
expression is an lvalue ... Otherwise, the reference shall be to a
non-volatile const type."
Both g++ 2.7.2 and Sun CC 3.0.1 (the old cfront version) issue
warnings about this. Curiously enough, Sun CC 4.0.1 doesn't, on this
platform (Sun CC 4.1), although I seem to remember warnings from this
compiler under Solaris. The Sun warnings state "anachronism", and in
fact, this rule was added to the language (at least five or six years
ago), so some older compilers may not be aware of it.
The rule was introduced to avoid errors in cases like the following:
void
incr( int& i )
{
i ++ ;
}
void
user()
{
unsigned x( 5 ) ;
incr( x ) ;
}
In the call to `incr', the compiler must convert x to an int; the
result of such a conversion is a temporary. Before the rule was
adapted, the temporary was bound to the reference, and modified by the
function `incr'. This is generally *NOT* what the author of user
wanted or expected (since `x' remains unchanged). Note that this is
not a problem with const references, since there is presumably no
modification to get lost.
The solution I'm using (since yesterday, when I thought of it:-) is to
add a function to T:
T&
T::lvalue()
{
return *this ;
}
And in the main, above:
int
main()
{
X x ;
x.f( T().lvalue() ) ;
return 0 ;
}
As you point out, the temporary isn't const, so I can call a non-const
function (like `lvalue') on it. And a reference *is* an lvalue (by
definition), so it can bind to a non-const reference.
This solution has the advantage (IMHO) of requiring the user to say,
yes, I know that I'm going to modify a temporary, but that's what I
want. It also retains const-safety; as the function `lvalue' is not
const, it cannot be called on a const object.
The major disadvantage is that it requires adding a function to T.
For classes where one expects this type of behavior (e.g.: auto_ptr),
one would probably add the function. But the user who needs it
exceptionally for a class where it is not the normal case is stuck.
(I have a case where I need it from ostrstream!) Of course, there is
always derivation:
class MyStrStream : public ostrstream
{
public :
ostrstream& lvalue() { return *this ; }
} ;
I'm not sure, but I think that `static_cast< T& >( T() )' should also
work. (This is OK for the occasional exceptional usage, but for cases
where I expect my user to normally use a temporary, I'll provide the
derived class.)
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils, études et réalisations en logiciel orienté objet --
-- A la recherche d'une activité dans une region francophone
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy is
summarized in http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
]
Technical Details
Message-ID:
<9602021214.AA07865@lts.sel.alcatel.de>Path:
arc1-ca.pugleaf.net!engnews1.Eng.Sun.COM!taumet!clamageReferences:
<4e6plv$idn@eclipse.eng.sc.rolm.com> <4eq5p2$fpu@fsuj01.rz.uni-jena.de>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!engnews1.Eng.Sun.COM!taumet!clamage From: James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de> Newsgroups: comp.std.c++ Subject: Re: Explicit constructor call vs Temporaries Date: 2 Feb 1996 15:49:12 GMT Organization: ? Approved: clamage@eng.sun.com (comp.std.c++) Message-ID: <9602021214.AA07865@lts.sel.alcatel.de> References: <4e6plv$idn@eclipse.eng.sc.rolm.com> <4eq5p2$fpu@fsuj01.rz.uni-jena.de> NNTP-Posting-Host: taumet.eng.sun.com Content-Type: text In-Reply-To: mkt@isun04.inf.uni-jena.de's message of 01 Feb 1996 09:54:08 PST Content-Length: 3667 X-Lines: 125 Originator: clamage@taumet