Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can't pass a temporary object by reference?

6 views
Skip to first unread message

Pieter van der meulen

unread,
Aug 12, 2001, 1:16:13 PM8/12/01
to
While porting a program from VC 6.0 to gcc 3.0 I noticed the following program
would not compile in gcc 3.0, but will in VC 6.0.

I can modify the program to pass a pointer to a sting (and get a warning),
pass the sting by value or interestingly by const reference and it compiles
fine? Why does gcc (and most likely the standard) behave this way?

The error rmessages I get are:
test.cpp: In function `int main()':
test.cpp:16: could not convert `string("Another string",
(&allocator<char>()))' to `std::string&'
test.cpp:7: in passing argument 1 of `void Print(std::string&)'

** begin code **
#include <iostream>
#include <string>

using namespace std;

void Print(string &str)
{
cout << str << endl;
}

int main()
{
string str("A string");
Print(str); // Works fine

Print(string("Another string")); // Won't compile in gcc 3

return 0;
}
** end code **

regards,

Pieter.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Gabriel Dos Reis

unread,
Aug 12, 2001, 2:13:35 PM8/12/01
to
p.g.m.van...@student.utwente.nl (Pieter van der meulen) writes:

| Print(string("Another string")); // Won't compile in gcc 3

Yes, you cannot bind a temporary to a non-const reference.

If that isn't a FAQ, it should.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

Shane Beasley

unread,
Aug 13, 2001, 12:58:16 AM8/13/01
to
Gabriel Dos Reis wrote:

> p.g.m.van...@student.utwente.nl (Pieter van der meulen) writes:
>
> | Print(string("Another string")); // Won't compile in gcc 3
>
> Yes, you cannot bind a temporary to a non-const reference.
>

Yes, but more to the point:

When taking a reference to data which is to be used in some operation
which should not alter that data (e.g., output), one should always use a
reference to const data (e.g., void foo (const int &ref)). In addition
to the guarantee that you will not change the data (not even
accidentally -- fewer bugs!), you can pass temporary data through such a
reference.

Also, a const reference allows for (gasp) implicit conversions, such as
that from const char * to std::string, such that this should compile:

Print("Another string"); // if Print takes a const std::string & as
an argument...

> If that isn't a FAQ, it should.

Yes, it probably should be. :)

It might also be nice for someone to explain *why*, in your words, "you
cannot bind a temporary to a non-const reference," but I am not that
someone. ;)

- Shane

Daniel T.

unread,
Aug 13, 2001, 8:18:32 AM8/13/01
to
p.g.m.van...@student.utwente.nl (Pieter van der meulen) wrote:

>While porting a program from VC 6.0 to gcc 3.0 I noticed the following
>program
>would not compile in gcc 3.0, but will in VC 6.0.
>
>I can modify the program to pass a pointer to a sting (and get a warning),
>pass the sting by value or interestingly by const reference and it
>compiles
>fine? Why does gcc (and most likely the standard) behave this way?

Because, by making the parameter a non-const reference, you are saying
that the changes to the parameter made by the function are important.

Passing in a temporary to the function makes it impossible for the
calling code to find out what changes were made to the object.

The way to fix your example code would be to change the parameter of the
Print function to a const reference or use pass by value.

Jason Carucci

unread,
Aug 13, 2001, 11:24:25 AM8/13/01
to
You should always define your functions as taking const params, unless they
need to change the value and pass it back to the calling function.

So define Print thus:

void Print(const string &str)
{
cout << str << endl;
}

it should work now.

Jason

"Pieter van der meulen" <p.g.m.van...@student.utwente.nl> wrote in
message news:9l664m$421$1...@dinkel.civ.utwente.nl...
<SNIP>


> void Print(string &str)
> {
> cout << str << endl;
> }
>

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Werle

unread,
Aug 13, 2001, 11:37:06 AM8/13/01
to
Shane Beasley <sbea...@eecs.uic.edu> writes:

> It might also be nice for someone to explain *why*, in your words, "you
> cannot bind a temporary to a non-const reference," but I am not that
> someone. ;)

I agree. If You call a function by value and the temporary
object gets copied, most compilers will optimize out that copy assignment and
build the object from scratch when used, so the - rather intuitive - use of
DoSomethingOnNonConstRef(BuildATemporary()); could be allowed here.

Look at this:
Mr. Alexandrescou writes in an article about "ScopeGuard" etc.
(I think I read this at www.cuj.com)

> According to the C++ standard, a const reference initialized with a temporary
> value makes that temporary value live for the lifetime of the reference
> itself.

Andrei uses this to avoid virtual destructors (!)
(They really _should_ put all this in MCD II)

After I had read that passage I am convinced that the
compiler-builder-headache-argument does not apply here.
If they already have to track the lifetime of all const refs that
point (sorry, refer) to some object, the job is done before
request.


What if we extended the temporary value lifetime rule to non-const references?
Would this change the language dramatically? Or can this be seen as a worthy
extension of C++?


Markus

--

Is Pluto a planet? No, Pluto is _not_ a Planet. It's a _minor_ Planet ;-)

Francis Glassborow

unread,
Aug 13, 2001, 11:47:13 AM8/13/01
to
In article <3B76D060...@eecs.uic.edu>, Shane Beasley
<sbea...@eecs.uic.edu> writes

>> If that isn't a FAQ, it should.
>
>Yes, it probably should be. :)

The problem is that sometimes it is not obvious that the problem is to
do with a FAQ. The knowledgeable can look at the question, get to the
key feature and recognise that it is just another instance of a FAQ. The
novice lacks that insight.


Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Francis Glassborow

unread,
Aug 13, 2001, 11:51:30 AM8/13/01
to
In article <notdanielt3-7BB1...@news.gte.net>, Daniel T.
<notda...@gte.net> writes

>The way to fix your example code would be to change the parameter of the
>Print function to a const reference or use pass by value.

Actually, making this fix is particularly important because as it is
currently specified, Print() cannot print out const, or const& instances
of the type. That would seem like a serious design error.

Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 13, 2001, 1:27:40 PM8/13/01
to
Markus Werle <mar...@lufmech.rwth-aachen.de> writes:

[...]

| What if we extended the temporary value lifetime rule to non-const
| references?

I don't know if it would change the language dramatically, but it
would break existing programs.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Marco Manfredini

unread,
Aug 13, 2001, 3:37:47 PM8/13/01
to
Markus Werle <mar...@lufmech.rwth-aachen.de> wrote in
news:tgn154m...@tresca.lufmech.RWTH-Aachen.DE:

AFAIK most compiler allow binding temporaries to nc-references, given
that you find the right commandline-switch. I don't understand the
rationale anyway. I hope it isn't something like "they are const because
they are r-values".

--
Marco

"Chapter 25 deals with the generalized subroutines for automatically
transforming lemmings into gold."

Michiel Salters

unread,
Aug 13, 2001, 3:39:52 PM8/13/01
to
In article <9l664m$421$1...@dinkel.civ.utwente.nl>, Pieter van der meulen says...

>
>While porting a program from VC 6.0 to gcc 3.0 I noticed the following program
>would not compile in gcc 3.0, but will in VC 6.0.
>
>I can modify the program to pass a pointer to a sting (and get a warning),
>pass the sting by value or interestingly by const reference and it compiles
>fine? Why does gcc (and most likely the standard) behave this way?

As others have (correctly) noted, this is by design.
Why does call by non-const reference fail?
What happens if a function takes a parameter by reference? The called
function is then able to modify the variable, and probably will do so.
If that parameter was a non-const reference to a temporary, the change
made by the called function will be lost when the temporary dies.

Why do const references work?
The called function promises not to change the temporary, so no
information is lost.

Why does pass-by-value work?
The called function works on a copy of the argument. The original
temporary can't be changed, and again no information is lost.

HTH,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel...@cmg.nl

Francis Glassborow

unread,
Aug 13, 2001, 5:19:33 PM8/13/01
to
In article <tgn154m...@tresca.lufmech.RWTH-Aachen.DE>, Markus Werle
<mar...@lufmech.rwth-aachen.de> writes

>What if we extended the temporary value lifetime rule to non-const
references?
>Would this change the language dramatically? Or can this be seen as a worthy
>extension of C++?

It would allow many more programming accidents. What is the gain to
balance that loss?


Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 13, 2001, 8:08:30 PM8/13/01
to
Shane Beasley <sbea...@eecs.uic.edu> writes:

| Gabriel Dos Reis wrote:
|
| > p.g.m.van...@student.utwente.nl (Pieter van der meulen) writes:
| >
| > | Print(string("Another string")); // Won't compile in gcc 3
| >
| > Yes, you cannot bind a temporary to a non-const reference.

[...]

| It might also be nice for someone to explain *why*, in your words, "you
| cannot bind a temporary to a non-const reference," but I am not that
| someone. ;)

I guess you won't accept "because the Standard says so" :-) in which
case you might want to consult D&E.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 14, 2001, 9:54:02 AM8/14/01
to
ma...@technoboredom.net (Marco Manfredini) writes:

[...]

| I hope it isn't something like "they are const because they are r-values".

Originally designed to support operator overloading, references in
conjunction with const qualification have proven to provide an
efficient substitution to pass-by-value function argument passing
mechanism ; in that respect it was seen important to prevent accidental
modification of the argument being passed.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Chris Newton

unread,
Aug 14, 2001, 9:57:12 AM8/14/01
to
Daniel T. wrote...

> Pieter van der meulen wrote:
>
> > While porting a program from VC 6.0 to gcc 3.0 I noticed
> > the following program would not compile in gcc 3.0, but
> > will in VC 6.0.

As an aside, VC++ provides a compiler-specific extension that allows
this behaviour. If you have your warning level set high enough, it will
issue a warning to this effect when you compile.

> > I can modify the program to pass a pointer to a sting (and
> > get a warning), pass the sting by value or interestingly by
> > const reference and it compiles fine? Why does gcc (and
> > most likely the standard) behave this way?

The rationale is that you're passing a temporary that will cease to
exist by the time the function call statement has finished executing.
Hence you could never act on any changes to that temporary, which is
"obviously" not what you wanted, and "must" be an unintentional error.
(Note that if there are really no changes to act on, it should be a
const reference that gets taken. Taking a non-const reference
effectively implies that something might happen to the passed data.)

> Because, by making the parameter a non-const reference, you
> are saying that the changes to the parameter made by the
> function are important.

Of course, it's absurd for a function to make that decision unilaterally
without knowing who's calling it or why, but we'll gloss over that.

> Passing in a temporary to the function makes it impossible for the
> calling code to find out what changes were made to the object.

Which is only a problem if it cares.

> The way to fix your example code would be to change the parameter
> of the Print function to a const reference or use pass by value.

True. Alternatively, of course, we could fix C++ by removing this rather
silly rule, and simply requiring the compiler to issue a warning
diagnostic instead.

Before anyone tells me I'm the one being silly and not the rule, ask
yourself when the last time was that you ignored any return value from
any function. Passing a temporary that you don't care about to a
function taking a reference is just the analogous way of ignoring an
"out" parameter. Of course, it may suggest that the interface you're
using is broken if this ever occurs, but maybe you don't have control of
that interface.

Regards,
Chris

Bill Trudell

unread,
Aug 14, 2001, 10:07:10 AM8/14/01
to
"Pieter van der meulen" <p.g.m.van...@student.utwente.nl> wrote in
message news:9l664m$421$1...@dinkel.civ.utwente.nl...
> While porting a program from VC 6.0 to gcc 3.0 I noticed the following
program
> would not compile in gcc 3.0, but will in VC 6.0.
>
> I can modify the program to pass a pointer to a sting (and get a warning),
> pass the sting by value or interestingly by const reference and it
compiles
> fine? Why does gcc (and most likely the standard) behave this way?

I looked at the library code for VC++ 6.0 (which I usually load when
installing studio) and I believe that the reason this line:

Print(string("Another string")); // Won't compile in gcc 3

compiles is that their library implements the return of string("Another
string") as a simple reference, not a constant reference. gcc probably
follows the standard closer.

Sincerely,

Bill Trudell

Markus Werle

unread,
Aug 14, 2001, 10:18:33 AM8/14/01
to
Francis Glassborow <francis.g...@ntlworld.com> writes:

> In article <tgn154m...@tresca.lufmech.RWTH-Aachen.DE>, Markus Werle
> <mar...@lufmech.rwth-aachen.de> writes
> >What if we extended the temporary value lifetime rule to non-const
> references?
> >Would this change the language dramatically? Or can this be seen as a
worthy
> >extension of C++?
>
> It would allow many more programming accidents. What is the gain to
> balance that loss?

Can You sketch such a possible accident?

Is this problem related to the fact that the caller site does
not see whether it's a call by value or a call by const/non-const
reference?

Markus

John W. Wilkinson

unread,
Aug 14, 2001, 10:20:16 AM8/14/01
to

Michiel Salters <Michiel...@cmg.nl> wrote in message
news:jVQd7.266$D4...@www.newsranger.com...

> In article <9l664m$421$1...@dinkel.civ.utwente.nl>, Pieter van der meulen
says...
> >
> >While porting a program from VC 6.0 to gcc 3.0 I noticed the following
program
> >would not compile in gcc 3.0, but will in VC 6.0.
> >
> >I can modify the program to pass a pointer to a sting (and get a
warning),
> >pass the sting by value or interestingly by const reference and it
compiles
> >fine? Why does gcc (and most likely the standard) behave this way?
>
> As others have (correctly) noted, this is by design.
> Why does call by non-const reference fail?
> What happens if a function takes a parameter by reference? The called
> function is then able to modify the variable, and probably will do so.
> If that parameter was a non-const reference to a temporary, the change
> made by the called function will be lost when the temporary dies.
>
> Why do const references work?
> The called function promises not to change the temporary, so no
> information is lost.
>
> Why does pass-by-value work?
> The called function works on a copy of the argument. The original
> temporary can't be changed, and again no information is lost.

I don't get it. With pass-by-value you create a copy, i.e. a 'temporary'.
This copy can be altered, any changes are then lost. What is the difference
between this and passing a temporary by-non-const-reference? In both cases a
temporary is created, and in both cases any changes to the temporary are
lost.

John

Markus Schaaf

unread,
Aug 14, 2001, 10:22:05 AM8/14/01
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote:

> In article <tgn154m...@tresca.lufmech.RWTH-Aachen.DE>, Markus Werle
> <mar...@lufmech.rwth-aachen.de> writes
> >What if we extended the temporary value lifetime rule to non-const
> >references? Would this change the language dramatically? Or can
> >this be seen as a worthy extension of C++?
>
> It would allow many more programming accidents.

Then make it a "diagnostic required" thing. There's no need to
_forbid_ binding temporaries to non-const references. IMO.

Markus Werle

unread,
Aug 14, 2001, 10:22:58 AM8/14/01
to
Michiel Salters<Michiel...@cmg.nl> writes:

> [...]


> As others have (correctly) noted, this is by design.
> Why does call by non-const reference fail?
> What happens if a function takes a parameter by reference? The called
> function is then able to modify the variable, and probably will do so.
> If that parameter was a non-const reference to a temporary, the change
> made by the called function will be lost when the temporary dies.

Why do we have to be sad about this? Is this really a damage that should
drive us to a restriction in the language that is in contradiction to (my
private) main paradigma of C++: "We can do it, but we must know what we do
and are responsible for any damage."

I have to remind You that this is not ADA. Well behaving programs and sound
design are harder to achieve in C++ than in any other language, but the
programmer's freedom has paid a lot. I have seen so many cases where
political incorrect abuses of this language led to the best solution one
could think of (see e.g. the dirty tricks done with templates and multiple
inheritance that lead to the possibility of aspect-oriented programming
without further changes to the language).

Some examples where I am not interested in the temporary:

As Herb Sutter has pointed out, resource acquisition is a nice tool for
writing exception-safe code. What if I put an action into a constructor
just in order to achieve stack unwinding etc. bla bla?
Using Constructors like functors ... why not?

What if I am _not_ interested in the object at all, but use (template)
classes to express structure: template metaprogramming?

I have a big headache right now with my BinOp<UnOp<etc>>, because every time
I have an operation working on the expression (like extraction of some
members) I need a true copy just to get that damn compiler satisfied.
Without usage of handlers You get a really bad run-time performance due to
the fact that it is extra work for the optimizer to find out that most of
the handlers point to the same structure. (Yes, indeed, most compilers do
not deal well with ET)

> [...]


> Why does pass-by-value work?
> The called function works on a copy of the argument. The original
> temporary can't be changed, and again no information is lost.

This means: The copy - an object - exists, but I never can reach it again
from outside the function. It is _swallowed_ by the function. So why not
just allow to only create an object, instead of create/copy to support this
special way of dealing with things?

Allowing non-const references is somewhat like having a std::auto_ptr taking
over object ownership, but _without_ all that pointer garbage. In the
reference case the function becomes owner of what I just built.

To say "Hello, Goodbye!" is useful sometimes.


Markus


--


Is Pluto a planet? No, but the only official decision belongs to the IAU.

Kevlin Henney

unread,
Aug 14, 2001, 10:24:40 AM8/14/01
to
In article <Xns90FCB6C52F65...@technoboredom.net>, Marco
Manfredini <ma...@technoboredom.net> writes

>AFAIK most compiler allow binding temporaries to nc-references, given
>that you find the right commandline-switch. I don't understand the
>rationale anyway. I hope it isn't something like "they are const because
>they are r-values".

It can get kind of interesting if you allow temporaries to bind to non-
consts, such as:

void Print(string &);

First of all, consider the unsurprising case that works in all
scenarios:

string s;
Print(s);

And then the explicit temporary case, which currently does not work but
is the subject of the thread:

Print(string("..."));

Well, if non-const reference binding to a temporary were permitted, this
would open the door to some implicit conversions:

Print("..."); // as if: Print(string("..."));

And don't forget that copy construction is a conversion:

const string s = "...";
Print(s); // as if: Print(string(s));

In other words, a non-const string reference is expected but a const
string is provided. A direct binding is not possible, but there would be
a conversion from a const string to a non-const string resulting in the
introduction of a temporary.

The language should not be modified to add surprises like this or to fix
const-incorrect code -- that would be solving the wrong problem ;->

Kevlin
____________________________________________________________

Kevlin Henney phone: +44 117 942 2990
mailto:kev...@curbralan.com mobile: +44 7801 073 508
http://www.curbralan.com fax: +44 870 052 2289
Curbralan: Consultancy + Training + Development + Review
____________________________________________________________

Gabriel Dos Reis

unread,
Aug 14, 2001, 11:02:17 AM8/14/01
to
"Markus Schaaf" <m.schaaf.e...@gmx.de> writes:

| "Francis Glassborow" <francis.g...@ntlworld.com> wrote:
|
| > In article <tgn154m...@tresca.lufmech.RWTH-Aachen.DE>, Markus Werle
| > <mar...@lufmech.rwth-aachen.de> writes
| > >What if we extended the temporary value lifetime rule to non-const
| > >references? Would this change the language dramatically? Or can
| > >this be seen as a worthy extension of C++?
| >
| > It would allow many more programming accidents.
|
| Then make it a "diagnostic required" thing. There's no need to
| _forbid_ binding temporaries to non-const references. IMO.

Requiring diagnostic doesn't prevent from breaking existing codes.
What are the wins?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 14, 2001, 11:06:23 PM8/14/01
to
In article <9lb1ep$8b81u$1...@ID-3706.news.dfncis.de>, Markus Schaaf
<m.schaaf.e...@gmx.de> writes

>> In article <tgn154m...@tresca.lufmech.RWTH-Aachen.DE>, Markus Werle
>> <mar...@lufmech.rwth-aachen.de> writes
>> >What if we extended the temporary value lifetime rule to non-const
>> >references? Would this change the language dramatically? Or can
>> >this be seen as a worthy extension of C++?
>>
>> It would allow many more programming accidents.
>
>Then make it a "diagnostic required" thing. There's no need to
>_forbid_ binding temporaries to non-const references. IMO.

What is the difference. An implementation can issue a diagnostic and
continue, some already do. What we do not do is require a diagnostic and
require the compiler to continue. Note that the standard only requires a
single diagnostic per TU in which there is code that requires
diagnostics. It does not require a per instance diagnostic.

Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 14, 2001, 11:06:41 PM8/14/01
to
In article <tghevbm...@tresca.lufmech.RWTH-Aachen.DE>, Markus Werle
<mar...@lufmech.rwth-aachen.de> writes

>> It would allow many more programming accidents. What is the gain to
>> balance that loss?
>
>Can You sketch such a possible accident?
>
>Is this problem related to the fact that the caller site does
>not see whether it's a call by value or a call by const/non-const
>reference?

When I pass by reference it is because I want the called function to
modify the original. Presumably because I want to capture the
consequence. If I do not want that I either pass by value (possibly
expensive in C++) or I pass by const ref. Now in both cases, the
compiler can apply conversions if the argument is not exactly what the
parameter expects. True that when this happens I loose the effciency of
pass by const ref.

Now if we allow temporaries to bind to non-const refs I can perpetrate
all kinds of silly things and left with far more debugging to do. For
example I can pass a string literal to a reference parameter and wonder
why the function appears to do nothing.

Not knowing whether a function accepts an argument by value or by const
ref is exactly to hide an implementation detail. The cost of that is
that we also hide passing to a non-const ref parameter. The very least
we can do is to make that behave like passing a pointer (not allowed for
temporaries)


Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Schaaf

unread,
Aug 15, 2001, 6:59:11 AM8/15/01
to
"Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote:

> | Then make it a "diagnostic required" thing. There's no need to
> | _forbid_ binding temporaries to non-const references. IMO.
>
> Requiring diagnostic doesn't prevent from breaking existing codes.

Puhleeze. There are compilers out there, that implement an extension
like this. Without breaking code. (You don't like it. Okay, that's
a point of view. But don't tell me it will break existing code.)

> What are the wins?

Flexibility.

Dave Harris

unread,
Aug 15, 2001, 7:02:38 AM8/15/01
to
Michiel...@cmg.nl (Michiel Salters) wrote (abridged):

> Why does call by non-const reference fail?
> What happens if a function takes a parameter by reference? The called
> function is then able to modify the variable, and probably will do so.
> If that parameter was a non-const reference to a temporary, the change
> made by the called function will be lost when the temporary dies.

That's not necessarily a problem, though. Compare with function return
results. C++ allows function return results to be ignored. Why shouldn't
it allow by-reference results to be ignored also?

long getValue() {
return 42;
}
void getValue( long &ref ) {
ref = 42;
}

Why is it more dangerous to ignore the result of the second version?

The real reason is because temporaries are sometimes created unexpectedly.
Eg:

void test() {
int value = 0;
getValue( value );
}

Here there is an implicit conversion from int to long. It is a widening
conversion so "safe"; it won't get a warning from the compiler. The
conversion creates a temporary and it is the temporary which would be
modified. This would surprise too many programmers.

In my view C++ should disallow binding of temporaries only when they
result from implicit conversions. Explicit conversions, or explicitly
created temporaries, should be allowed. This would make expressions more
useful (since a temporary is just the result of an expression).

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

Marco Manfredini

unread,
Aug 15, 2001, 10:11:50 AM8/15/01
to
Kevlin Henney <kev...@curbralan.com> wrote in
news:3g659EBg...@curbralan.com:

> In article <Xns90FCB6C52F65...@technoboredom.net>,
> Marco Manfredini <ma...@technoboredom.net> writes
>>AFAIK most compiler allow binding temporaries to nc-references,
>>given that you find the right commandline-switch. I don't
>>understand the rationale anyway. I hope it isn't something like
>>"they are const because they are r-values".
>

> It can get kind of interesting if you allow temporaries to bind to
> non- consts, such as:

[snip examples showing what const references try to prevent]

For me, the rule tries to solve a problem with the wrong means.
Temporaries are not const, but you cannot name them without ending with
a const reference. It looks like there is too much pushed into it, to
make the argument generation safe enough. By the same time it creates
annoying phaenomenons as in:

class A{};
class Q{public: void foo() {}};
int main()
{
Q().foo(); // ok!
A &a=Q(); // not ok!
a.foo(); // pffft.
}
[this is what the compilers allow, when you find the right switch. I am
not aware btw. that a compiler allows binding temporaries to nc-
references in /argument passing/]

>
> The language should not be modified to add surprises like this or
> to fix const-incorrect code -- that would be solving the wrong
> problem ;->

The languages shouldn't solve too many problems through feature overload
either.

--
Marco

"Chapter 25 deals with the generalized subroutines for automatically
transforming lemmings into gold."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 15, 2001, 10:13:02 AM8/15/01
to
In article <9l9jqm$mhs$1...@uranium.btinternet.com>, Chris Newton
<chris...@no.junk.please.btinternet.com> writes

>> The way to fix your example code would be to change the parameter
>> of the Print function to a const reference or use pass by value.
>
>True. Alternatively, of course, we could fix C++ by removing this rather
>silly rule, and simply requiring the compiler to issue a warning
>diagnostic instead.

In other words you want us to change the language to fix badly written
code. Sorry, but we have better things to do with our time.

>
>Before anyone tells me I'm the one being silly and not the rule, ask
>yourself when the last time was that you ignored any return value from
>any function. Passing a temporary that you don't care about to a
>function taking a reference is just the analogous way of ignoring an
>"out" parameter.

But what I care about is having a language which questions me when I am
being silly. Actually I could make a good argument for going the other
way and requiring a diagnostic when a return value is ignored.
Unfortunately that would have some dire results on assignment
expressions where ultimately you just about have to ignore the return
value. (There are uses of casting to void to handle problems like this.)

>Of course, it may suggest that the interface you're
>using is broken if this ever occurs, but maybe you don't have control of
>that interface.

Then howl at the person who does for writing bad code. In the meantime
you have a perfectly good work around by creating explicit instances
before calling the function:

{ string temp = "Hello World";
Print (temp);
}

Both works and highlights the fact that you are 'cheating'. Many would
think that was good coding practice; make explicit the places where you
are walking on a knife edge.

Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Anthony Williams

unread,
Aug 15, 2001, 10:15:09 AM8/15/01
to
"Kevlin Henney" <kev...@curbralan.com> wrote in message
news:3g659EBg...@curbralan.com...

These problems would not arise if you did not permit a non-const reference
to bind to the result of an implicit conversion.

Thus

string s;
const string cs="hello";
Print(s); // OK
Print("hello"); // Error
Print(string("hello")); // OK
Print(cs); //Error
Print(string(cs)); // OK

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer

Maciej Sobczak

unread,
Aug 15, 2001, 10:15:28 AM8/15/01
to
Hi,

"Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote in message
news:fl4rras...@pizza.cmla.ens-cachan.fr...


> "Markus Schaaf" <m.schaaf.e...@gmx.de> writes:
>
> | "Francis Glassborow" <francis.g...@ntlworld.com> wrote:
> |
> | > In article <tgn154m...@tresca.lufmech.RWTH-Aachen.DE>, Markus
Werle
> | > <mar...@lufmech.rwth-aachen.de> writes
> | > >What if we extended the temporary value lifetime rule to non-const
> | > >references? Would this change the language dramatically? Or can
> | > >this be seen as a worthy extension of C++?
> | >
> | > It would allow many more programming accidents.
> |
> | Then make it a "diagnostic required" thing. There's no need to
> | _forbid_ binding temporaries to non-const references. IMO.
>
> Requiring diagnostic doesn't prevent from breaking existing codes.
> What are the wins?

I don't understand exactly *what* existing code would break.
If binding a temporary to non-const ref is prohibited now (forget strange
extensions and non-conformance), then there is *no* compliant code around
which behaviour could've been altered by officially allowing it. There is
just nothing to break.

(Note that) I'm perfectly happy with what we have now and I agree with those
who claim that changing it would be bad: I don't want this dubious "feature"
in the language. But I'm curious about your reasoning.
It's likely that I lack some deeper insight and there really is a possible
(now compliant) code that would be vulnerable to such a change. What code
examples do you mean?

Thanks!

--
Interested in distributed, object-based programming?
Complete and consistent environment for Linux, Windows, ..., C, C++, ASP,
VB, ...
check: http://www.cern.ch/maciej/prog/yami

Maciej Sobczak, http://www.cern.ch/Maciej.Sobczak
"in theory, there is no difference between theory and practice - but in
practice, there is"

James Kanze

unread,
Aug 15, 2001, 11:35:29 AM8/15/01
to
"Chris Newton" <chris...@no.junk.please.btinternet.com> wrote in
message news:<9l9jqm$mhs$1...@uranium.btinternet.com>...

> > The way to fix your example code would be to change the parameter
> > of the Print function to a const reference or use pass by value.

> True. Alternatively, of course, we could fix C++ by removing this
> rather silly rule, and simply requiring the compiler to issue a
> warning diagnostic instead.

The rule was added as a result of experience. Errors DID occur
without it.

The real problem isn't, of course, binding an rvalue to a reference,
but the fact that implicit conversions often result in unexpected
rvalues. The example of the problem was something along the lines of:

void
incr( int& i )
{
++ i ;
}

void
f()
{
unsigned x = 3 ;
incr( x ) ;
}

Without the rule, x silently converts to an int, and a reference to
the converted temporary is passed.

I would argue that the problem is the silent conversions, and not the
binding to a reference. But let's face it: there's no way we can ever
ban the implicit conversion of short to int; even a proposal to
deprecate lossy conversions was voted down by the committee.

One alternative that has been proposed is to only ban the binding if
the temporary is the result of an implicit conversion. On the face of
it, it sounds reasonable, but it is certainly an additional
complication in function overloading, a subject which isn't
particularly free of complications as is.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

James Kanze

unread,
Aug 15, 2001, 12:06:37 PM8/15/01
to
"John W. Wilkinson" <john.wilkinson@remove_this.gssl.co.uk> wrote in
message news:<99778533...@ananke.eclipse.net.uk>...

> I don't get it. With pass-by-value you create a copy, i.e. a
> 'temporary'. This copy can be altered, any changes are then
> lost. What is the difference between this and passing a temporary
> by-non-const-reference? In both cases a temporary is created, and in
> both cases any changes to the temporary are lost.

If I call a function using call by value, I know that my parameter
object will not be modified. If I call a function taking a non-const
reference, I expect any modifications in the parameter to be reflected
in the object I passed.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Werle

unread,
Aug 15, 2001, 3:48:59 PM8/15/01
to
Francis Glassborow <francis.g...@ntlworld.com> writes:

> Now if we allow temporaries to bind to non-const refs I can perpetrate
> all kinds of silly things

Yes, I think we should be allowed to do silly things.
Sometimes they seem to be the most appropriate thing to do.

Some people overwrite non-virtual destructors and - safely - gain
runtime performance. What would happen if this was not allowed ...

> and left with far more debugging to do.

I express what I want and it is done in C++.
As always I really have to know what I do.

If I do not want to think about what I do,
I should switch the language anyway.

> example I can pass a string literal to a reference parameter and wonder
> why the function appears to do nothing.

I do not understand at all. Could someone give a small code example?

> Not knowing whether a function accepts an argument by value or by const
> ref is exactly to hide an implementation detail.

No. The caller _must_ read the header and must be aware of the cost of a
possible copy operation. She must look at the header anyway because for
non-temporaries the non-const reference call is allowed. So nothing we
can really hide here.

The most stupid library user will always find a way to break things up.

> The cost of that is
> that we also hide passing to a non-const ref parameter. The very least
> we can do is to make that behave like passing a pointer (not allowed for
> temporaries)

But easy to implement for the compiler vendor.
Most have already done so and disabled them afterwards. Why?


Restart:

It may be that disallowing non-const references is the correct decision.
My intention is to find out the what and why.

I am sorry for not having access to "The design and evolution of C++"
which may have some hints on this. I currently lack the money for
yet another book on C++ (MCD was just too expensive - but worth the money)
so I request that info from the NG.

Sad enough Your arguments until now did not convince me at all.

So I ask the following questions:

* Can allowing of non-const reference break the semantics of
_existing_ code? Please give an example where existing code
changes its behaviour when compilers allow non-const refs.

To make it harder for You: the example must top the severity of the
for-loop changes in the standard ;-).


* Are there severe implications on the development process,
e.g.

- large probability of hard-to-detect errors which drive experienced
c++-programmers up the wall

- Is it impossible to detect possible problems with this feature by
development tools so that migrating existing code cannot be automated?


* Are there any other problems I have not seen yet?


In _any_ case please give concrete code examples which
lead to a thorough understanding of the implications.

My impression is that the non-const-reference discussion is similar
to the multiple inheritance stuff: the OO-purists say "no" (like in Ada)
and the specialists make heavy use of it when it enters the standard
(producing better OO-designs than the purists)

And here again I say until code examples convince me of the opposite:
The gain of adding this feature weights its possible drawbacks.


Markus

James Dennett

unread,
Aug 15, 2001, 4:32:37 PM8/15/01
to

The most persuasive argument I've seen (not quite) stated for
disallowing binding temporaries to non-const references is
based on the fact that adding const could then silently change
the meaning of existing code. That's also the best argument
agaisnt having "delete p;" set p to null in the case of 'p'
being a non-const lvalue.

Assume we have:

class X { ... };
void modify(X &) { ... };
...
X x;
modify(x);

Given current C++ rules, we know that "modify" changes the
variable "x". Now, in real code "modify" probably doesn't
have such an explicit name, and one day a (junior?)
programmer with good intentions will come along and add
const wherever possible.

Changing to "void modify(const X&) { ...}" will fail, if
X has a properly designed interface, so the novice won't
change that.

Changing to "const X x" will also fail with current rules.
If we changed to allow binding a non-const reference to a
temporary, this change would become legal, and the code
would be changed to be (roughly) equivalent to:

const X x;
modify(X(x));

because a copy constructor can be used for conversion.
More explicitly, this is roughly the same as

const X x;
{
X __auto_generated_temporary(x);
modify(__auto_generated_temporary);
}

and the meaning of our code has silently change when we
added const. Bad.

The argument for deletion of a pointer relies on code
such as

X *p = new X;
delete p;
// ...
if (!p) // ...

Assume that delete p can null its (non-const, lvalue)
argument, so that the above snippet is well-defined.
Programmers who want delete to null its argument often
(though not always) want this behaviour to be reliable.

Then our well-intentioned novice changes the code to

X *const p = new X;
delete p;
// ...
if (!p) // ...

and finds himself breathing out demons of undefined
behaviour for accessing the value of 'p' after the
memory to which 'p' did point was deleted. Most likely
the result of that undefined behaviour is to change the
result of the condition of the if, clearly changing
(and almost surely breaking) the logic of the code.

-- James Dennett

Gabriel Dos Reis

unread,
Aug 15, 2001, 5:14:35 PM8/15/01
to
"Maciej Sobczak" <Maciej....@cern.ch> writes:

[...]

| I don't understand exactly *what* existing code would break.

The outcome of overloading resolution, for example.

| If binding a temporary to non-const ref is prohibited now (forget strange
| extensions and non-conformance), then there is *no* compliant code around
| which behaviour could've been altered by officially allowing it. There is
| just nothing to break.

You are missing one important piece of how C++ works: Because that
construct is ill-formed, some functions will be discarded in the
process of overloading resolution. If you allow them, you'll change
the result of that process.

The mere fact that a construct is ill-formed now isn't a sufficient
condition to ensure that its hypothetical inclusion in the next
version of C++ won't break existing codes. Sorry, it isn't that simple.

[...]

| What code examples do you mean?

See my other posting.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Werle

unread,
Aug 15, 2001, 8:06:01 PM8/15/01
to
Kevlin Henney <kev...@curbralan.com> writes:

> Well, if non-const reference binding to a temporary were permitted, this
> would open the door to some implicit conversions:
>
> Print("..."); // as if: Print(string("..."));

Is this really so bad? Implicit conversions crop up everywhere.
Keyword explicit may help?

> And don't forget that copy construction is a conversion:
>
> const string s = "...";
> Print(s); // as if: Print(string(s));
>
> In other words, a non-const string reference is expected but a const
> string is provided. A direct binding is not possible, but there would be
> a conversion from a const string to a non-const string resulting in the
> introduction of a temporary.

Besides the fact that this problem already has to be paid attention of:
we could disallow this or warn about it (how easy for the compiler!).
Implicit conversions were disabled for templates to point programers
to logical errors. Why not do the same here if it really turns out to be
a problem?

> The language should not be modified to add surprises like this or to fix
> const-incorrect code -- that would be solving the wrong problem ;->

It solves other problems connected to compile time calculations.


Markus

Gabriel Dos Reis

unread,
Aug 15, 2001, 8:13:21 PM8/15/01
to
"Markus Schaaf" <m.schaaf.e...@gmx.de> writes:

| "Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote:
|
| > | Then make it a "diagnostic required" thing. There's no need to
| > | _forbid_ binding temporaries to non-const references. IMO.
| >
| > Requiring diagnostic doesn't prevent from breaking existing codes.
|
| Puhleeze.

Pardon?

#include <iostream>

struct X {

void f() { std::cout << "non-const\n"; }
void f() const { std::cout << "const\n"; }
};

void forward_f(X& x)
{ x.f(); }

void forward_f(const X& x)
{ x.f(); }

int main()
{
X x;
forward_f(x);
forward_f(X());
}

-- Gaby

Markus Schaaf

unread,
Aug 15, 2001, 8:14:42 PM8/15/01
to
"Kevlin Henney" <kev...@curbralan.com> wrote:

> const string s = "...";
> Print(s); // as if: Print(string(s));
>
> In other words, a non-const string reference is expected but a const
> string is provided. A direct binding is not possible, but there would be
> a conversion from a const string to a non-const string resulting in the
> introduction of a temporary.

And this is the only thing that the programmer could have
intended: call "Print" but don't modify "s", because it is
"const". Please remember that this code will not work with
a standard conforming compiler. So there could be really no
other interpretation of this line of code.

Of course, you might say that allowing new contructs may be
dangerous. Yes, that's true. But there is much more in C++
which is potentially dangerous. As another poster pointed
out: I wouldn't have used C++ as programming language, if
my major concern was avoiding potentially dangerous code.
Ada already exists. There is no need to reinvent it.

Francis Glassborow

unread,
Aug 16, 2001, 1:51:52 AM8/16/01
to
In article <9ld849$8nghl$1...@ID-49767.news.dfncis.de>, Anthony Williams
<ant...@nortelnetworks.com> writes

>These problems would not arise if you did not permit a non-const reference
>to bind to the result of an implicit conversion.


And the problem (certainly for this example) does not arise if the code
is written correctly.


>
>Thus
>
>string s;
>const string cs="hello";
>Print(s); // OK


NO this should not be OK, cs is const and should not be bound to a nc
reference. I do not object too strongly to compilers that issue a
diagnostic and then create a temporary but it is still a badll flawed
design, even though it is a common error.


>Print("hello"); // Error
>Print(string("hello")); // OK
>Print(cs); //Error
>Print(string(cs)); // OK


If you want a language change, produce an example where well-designed
code benefits from allowing temporaries to bind to nc refs.


Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Schaaf

unread,
Aug 16, 2001, 7:46:40 AM8/16/01
to
"Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote:

> "Maciej Sobczak" <Maciej....@cern.ch> writes:
>
> | If binding a temporary to non-const ref is prohibited now (forget strange
> | extensions and non-conformance), then there is *no* compliant code around
> | which behaviour could've been altered by officially allowing it. There is
> | just nothing to break.
>
> You are missing one important piece of how C++ works: Because that
> construct is ill-formed, some functions will be discarded in the
> process of overloading resolution. If you allow them, you'll change
> the result of that process.

You don't need to change overload resolution while allowing
temporaries to get bound to non-const references. Binding to
non-const would be the worst case, and if an overload takes
a const reference, then that is prefered as ever. In other
words: only if compilation would abort, because no matching
overload could be found, then (as an additional step)
functions taking a non-const reference would be considered.

Dave Harris

unread,
Aug 16, 2001, 7:48:43 AM8/16/01
to
jden...@acm.org (James Dennett) wrote (abridged):

> More explicitly, this is roughly the same as
>
> const X x;
> {
> X __auto_generated_temporary(x);
> modify(__auto_generated_temporary);
> }
>
> and the meaning of our code has silently change when we
> added const. Bad.

As before, the real problem is the implicit temporary which resulted from
an implicit conversion. The proposed rule - non-const references binding
to temporaries only if they are not implicitly generated - would reject
this case too.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 16, 2001, 7:52:07 AM8/16/01
to
Markus Werle <mar...@lufmech.rwth-aachen.de> writes:

| we could disallow this or warn about it (how easy for the compiler!).

What does it mean in Standardese that a diagnostic should be required
for a well-formed construct?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 16, 2001, 8:11:51 AM8/16/01
to
Markus Werle <mar...@lufmech.rwth-aachen.de> writes:

[...]

| The most stupid library user will always find a way to break things up.

Those words apply very well to current state, so they surely aren't
argument for changing the language in that respect.

[...]

| * Can allowing of non-const reference break the semantics of
| _existing_ code?

Unambigously, yes. See my other posting.

[...]

| My impression is that the non-const-reference discussion is similar
| to the multiple inheritance stuff: the OO-purists say "no" (like in Ada)
| and the specialists make heavy use of it when it enters the standard
| (producing better OO-designs than the purists)

That parallel is far fetched.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Chris Newton

unread,
Aug 16, 2001, 8:12:44 AM8/16/01
to
Francis Glassborow <francis.g...@ntlworld.com> wrote...

> When I pass by reference it is because I want the called
> function to modify the original.

Nope, it's because the person who wrote the function you're calling
decided to take a reference parameter. What you want, as the person
calling it, is unfortunately completely irrelevant.

Herein lies the flaw with most of the arguments in favour of status quo
on this thread. They presuppose that you are working with an interface
over which you have control. Frequently, this is not the case, and it's
then that the ability to pass a temporary as a non-const reference can
be useful.

The sounder argument for status quo is the creation of unexpected
temporaries, particularly things like creation of a non-const temporary
copy of a const object, when you would expect trying to pass an
explicitly const object as a non-const reference would result in an
error. However, one could reasonably suggest alternatives in most of
these cases without thinking too hard. As long as a warning diagnostic
is required, I don't see things like a conversion of an int to a
temporary long as a problem.

It's not like C++ is a language that chooses safety over flexibility in
most other circumstances, after all. Quite the contrary in fact; indeed,
one could argue that much of its success is due to the fact that it
*doesn't* stop me doing apparently silly things, if I deliberately
choose to do so and have my reasons. I've never understood why an
anti-philosophy decision was made in this case.

Cheers,
Chris

Maciej Sobczak

unread,
Aug 16, 2001, 8:13:21 AM8/16/01
to
Hi,

"Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote in message

news:fllmklm...@jambon.cmla.ens-cachan.fr...


> "Maciej Sobczak" <Maciej....@cern.ch> writes:
>
> | I don't understand exactly *what* existing code would break.
>
> The outcome of overloading resolution, for example.

> Because that
> construct is ill-formed, some functions will be discarded in the
> process of overloading resolution. If you allow them, you'll change
> the result of that process.
>

> See my other posting.

You mean - the one with forwarding functions.
Yes, you're right. I've played a bit with my compiler's switches and
*really* got different results, depending on the presence of this extension.
This is a bloody silent change, not reported by the compiler until set to
highest possible warning level.
Now I know what you've meant by 'breaking the code'. I've expected
compile-time errors and got nasty run-time differences instead.
I've missed the overloading process.

Thanks for explanation!

--
Interested in distributed, object-based programming?
Complete and consistent environment for Linux, Windows, ..., C, C++, ASP,
VB, ...
check: http://www.cern.ch/maciej/prog/yami

Maciej Sobczak, http://www.cern.ch/Maciej.Sobczak
"in theory, there is no difference between theory and practice - but in
practice, there is"

Anthony Williams

unread,
Aug 16, 2001, 8:13:39 AM8/16/01
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:aIETOKAt...@ntlworld.com...

> In article <9ld849$8nghl$1...@ID-49767.news.dfncis.de>, Anthony Williams
> <ant...@nortelnetworks.com> writes
> >These problems would not arise if you did not permit a non-const
reference
> >to bind to the result of an implicit conversion.
>
>
> And the problem (certainly for this example) does not arise if the code
> is written correctly.
> >
> >Thus
> >
> >string s;
> >const string cs="hello";
> >Print(s); // OK
>
>
> NO this should not be OK, cs is const and should not be bound to a nc
> reference. I do not object too strongly to compilers that issue a
> diagnostic and then create a temporary but it is still a badll flawed
> design, even though it is a common error.

The example above was passing s, the non-const string, so it's OK.

> >Print("hello"); // Error
> >Print(string("hello")); // OK
> >Print(cs); //Error
> >Print(string(cs)); // OK
>
>
> If you want a language change, produce an example where well-designed
> code benefits from allowing temporaries to bind to nc refs.

Template forwarding functions. The following is insufficient for use with
temporaries, as T& will never deduce to be "const X&" for a temporary.

template<typename FunctionType,typename T>
void functionForwarder(FunctionType f, T& t)
{
f(t);
}

void myfunc(int i);

int i=0;
functionForwarder(myfunc,i); // OK
const int j=0;
functionForwarder(myfunc,j); // OK
functionForwarder(myfunc,3); // error

Adding an overload

template<typename FunctionType,typename T>
void functionForwarder(FunctionType f, const T& t)
{
f(t);
}

doesn't work either, because the validity of the resulting function isn't
considered when selecting overloaded templates, and so the first is always
chosen over the second for a non-const rvalue.

If a temporary can bind to a non-const ref, then the first template is
sufficient on its own.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer

John W. Wilkinson

unread,
Aug 16, 2001, 8:13:57 AM8/16/01
to

James Kanze <ka...@gabi-soft.de> wrote in message
news:d6651fb6.01081...@posting.google.com...

> "John W. Wilkinson" <john.wilkinson@remove_this.gssl.co.uk> wrote in
> message news:<99778533...@ananke.eclipse.net.uk>...
> > I don't get it. With pass-by-value you create a copy, i.e. a
> > 'temporary'. This copy can be altered, any changes are then
> > lost. What is the difference between this and passing a temporary
> > by-non-const-reference? In both cases a temporary is created, and in
> > both cases any changes to the temporary are lost.
>
> If I call a function using call by value, I know that my parameter
> object will not be modified. If I call a function taking a non-const
> reference, I expect any modifications in the parameter to be reflected
> in the object I passed.

Thanks, but I was quite aware of the difference between call-by-value and
call by non-const-reference.

If you reread the thread you should see that I was questioning Michiel
Salters's explanation of why the language stops temporaries from being
passed by non-const-reference.

I disagreed with the proposition that this was because changes to the
temporary would be lost. Other people has subsequently given IMHO better
reasons, see Dave Harris's post.

John

Chris Newton

unread,
Aug 16, 2001, 8:49:54 AM8/16/01
to
Marco Manfredini <ma...@technoboredom.net> wrote...

> For me, the rule tries to solve a problem with the
> wrong means. Temporaries are not const, but you
> cannot name them without ending with a const
> reference. It looks like there is too much pushed
> into it, to make the argument generation safe
> enough. By the same time it creates annoying
> phaenomenons as in:
>
> class A{};
> class Q{public: void foo() {}};
> int main()
> {
> Q().foo(); // ok!
> A &a=Q(); // not ok!
> a.foo(); // pffft.
> }

Unfortunately, that's a prime example of why the rule is there in the
first place. The statement
a.foo();
above acts on a temporary that no longer exists, which is patently
undefined behaviour (except that, of course, this situation doesn't
happen in standard C++, because it can't).

Cheers,
Chris

Markus Werle

unread,
Aug 17, 2001, 12:25:37 AM8/17/01
to
James Dennett <jden...@acm.org> writes:

> [ snipped 2 good examples how codes get broken]

Thank You for providing these.

Again I retake a proposal from other posters:
References to temporaries may only enter the standard
if implicit conversion is disallowed.

Now I guess that neither function overloading resolution nor
const conversion will take place and the compiler is able
to find the stupid errors.

Any situation where code breaks up even with this rule?


Markus

Francis Glassborow

unread,
Aug 17, 2001, 12:28:45 AM8/17/01
to
In article <9ldp0t$85j6d$1...@ID-3706.news.dfncis.de>, Markus Schaaf
<m.schaaf.e...@gmx.de> writes

>Of course, you might say that allowing new contructs may be
>dangerous. Yes, that's true. But there is much more in C++
>which is potentially dangerous. As another poster pointed
>out: I wouldn't have used C++ as programming language, if
>my major concern was avoiding potentially dangerous code.
>Ada already exists. There is no need to reinvent it.

Surely we should be working to reduce potentially dangerous code, not
taking its existence as an excuse for adding more.

I have already shown how there is a work round, that actually documents
the programmer's understanding. And that work round is only necessary if
the function is badly designed (either it should take a const qualified
reference, or it does more than you need and should have been
refactored. However consider:

mytype& foo (mytype & mtr) {
// do work
return mtr;
}

Now, under the proposed modification, that creates something very
surprising and potentially very dangerous (to writing reliable code).
Even:

mytype const& foo (mytype & mtr) {
// do work
return mtr;
}

Is going to be problematical as the compiler (possibly only seeing the
decl) will now almost certainly destroy the temporary early.


Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos_Reis

unread,
Aug 17, 2001, 12:29:51 AM8/17/01
to
"Markus Schaaf" <m.schaaf.e...@gmx.de> writes:

| "Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote:
|
| > "Maciej Sobczak" <Maciej....@cern.ch> writes:
| >
| > | If binding a temporary to non-const ref is prohibited now (forget
strange
| > | extensions and non-conformance), then there is *no* compliant code
around
| > | which behaviour could've been altered by officially allowing it. There
is
| > | just nothing to break.
| >
| > You are missing one important piece of how C++ works: Because that
| > construct is ill-formed, some functions will be discarded in the
| > process of overloading resolution. If you allow them, you'll change
| > the result of that process.
|
| You don't need to change overload resolution while allowing
| temporaries to get bound to non-const references.

I didn't say one needs to change overloading resolution rules. I said
that if you allow a temporary to be bound to a non-const reference,
*then* implicitly you change the outcome of overloading resolution
process.

| Binding to
| non-const would be the worst case, and if an overload takes
| a const reference, then that is prefered as ever.

Then you *do* change current overloading rules.
Please, firstly, agree with yourself ;-)

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 17, 2001, 12:30:09 AM8/17/01
to
In article <9lft2t$96td5$1...@ID-49767.news.dfncis.de>, Anthony Williams
<ant...@nortelnetworks.com> writes

>Template forwarding functions. The following is insufficient for use with
>temporaries, as T& will never deduce to be "const X&" for a temporary.
>
>template<typename FunctionType,typename T>
>void functionForwarder(FunctionType f, T& t)
>{
> f(t);
>}
That is fine as long as f() does not attempt to modify t. That is as it
should be IMO.
>
>void myfunc(int i);
ah, I see, you want to use it with a function that takes an argument by
value.

>
>int i=0;
>functionForwarder(myfunc,i); // OK
>const int j=0;
>functionForwarder(myfunc,j); // OK
>functionForwarder(myfunc,3); // error
>
>Adding an overload
>
>template<typename FunctionType,typename T>
>void functionForwarder(FunctionType f, const T& t)
>{
> f(t);
>}
>
>doesn't work either, because the validity of the resulting function isn't
>considered when selecting overloaded templates, and so the first is always
>chosen over the second for a non-const rvalue.
>
>If a temporary can bind to a non-const ref, then the first template is
>sufficient on its own.

OK, I understand the problem, but think you have the wrong solution. I
think the problem is that literals have the wrong type. Culd we explore
the ramifications of making literals (including explicitly constructed
temporaries) have const qualification? FWIW I have always found making
the type of '5' an int an affront to common sense when it is clearly of
type const int, and indeed is treated that way by the compiler when used
for initialisation.
I.e the compiler does not distinguish between:

int const max=100;
mytype data[max];

and

mytype data[100];

Apparently 100 is a constant expression but not a constant:)

Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 17, 2001, 12:30:28 AM8/17/01
to
In article <9leb6m$pg1$1...@neptunium.btinternet.com>, Chris Newton
<chris...@no.junk.please.btinternet.com> writes

>Francis Glassborow <francis.g...@ntlworld.com> wrote...
>> When I pass by reference it is because I want the called
>> function to modify the original.
>
>Nope, it's because the person who wrote the function you're calling
>decided to take a reference parameter. What you want, as the person
>calling it, is unfortunately completely irrelevant.

But I have already provided a perfectly reasonable work round where the
designer of the function is incompetent, or where you are willing to
trash the use of the parameter as an out parameter


>
>Herein lies the flaw with most of the arguments in favour of status quo
>on this thread. They presuppose that you are working with an interface
>over which you have control. Frequently, this is not the case, and it's
>then that the ability to pass a temporary as a non-const reference can
>be useful.

Then write:

{
mytype mt(/*...*/);
foo(mt);
}

>
>The sounder argument for status quo is the creation of unexpected
>temporaries, particularly things like creation of a non-const temporary
>copy of a const object, when you would expect trying to pass an
>explicitly const object as a non-const reference would result in an
>error. However, one could reasonably suggest alternatives in most of
>these cases without thinking too hard. As long as a warning diagnostic
>is required, I don't see things like a conversion of an int to a
>temporary long as a problem.

You insist on wanting an entirely new type of diagnostic - one applied
to well formed code. Compilers can issue warnings, and often do, before
carrying out the intent of ill-formed code. But having required
diagnostics on well formed code is an entirely different thing.

>
>It's not like C++ is a language that chooses safety over flexibility in
>most other circumstances, after all. Quite the contrary in fact; indeed,
>one could argue that much of its success is due to the fact that it
>*doesn't* stop me doing apparently silly things, if I deliberately
>choose to do so and have my reasons. I've never understood why an
>anti-philosophy decision was made in this case.

Some of us want to reduce these problems, you seem to want to increase
them. Some of us want a safer C++.

Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gary Mussar

unread,
Aug 17, 2001, 12:32:33 AM8/17/01
to
"James Kanze" <ka...@gabi-soft.de> wrote in message
news:d6651fb6.01081...@posting.google.com...
> If I call a function using call by value, I know that my parameter
> object will not be modified. If I call a function taking a non-const
> reference, I expect any modifications in the parameter to be reflected
> in the object I passed.

Slightly off topic: That is of course assuming that the object has
non-destructive copy semantics. I've had to deal with a number of classes
where the original designer made the copy semantics transfer resources from
the source to the destination object (ie. a copy ctor with a non-const
reference parameter). Classes with this type of semantic cause all sorts of
problems because passing by value will affect the source object.

Gary

Chris Newton

unread,
Aug 17, 2001, 10:52:29 AM8/17/01
to
Francis Glassborow <francis.g...@ntlworld.com> wrote...
> Chris Newton writes...

> >True. Alternatively, of course, we could fix C++ by
> >removing this rather silly rule, and simply requiring
> >the compiler to issue a warning diagnostic instead.
>
> In other words you want us to change the language to fix
> badly written code. Sorry, but we have better things to do
> with our time.

Too bad. Since about 90% of the code I work with is badly written, even
if I and the language I use are perfect, I'm still screwed if I adopt
that attitude.

Are you by any chance a friend of the person who thought making
new-style casts ugly as sin was a good idea (and in the process,
immediately ensured that most programs that could benefit from a good
idea will never do so)?

[...]

> >Of course, it may suggest that the interface you're
> >using is broken if this ever occurs, but maybe you
> >don't have control of that interface.
>
> Then howl at the person who does for writing bad code.

I can't. They were contractors, and they left the company before I even
joined. Do you not see the simple real-world problem here? I do not
have control of most of the "bad code".

Furthermore, while I could theoretically "fix" some of the poor
interfaces I work with, I will not be authorised to do so. We, and our
clients, have invested months testing the application. Any change in a
given area immediately invalidates some of those tests and leads to the
cost of retesting to make sure nothing's been broken. At present, it's
not broken and is known to work, it's just not as good as it could have
been. That does not justify changing it.

Given these two basic problems, I have to work with things as they are.
The current rule is not helping me.

> In the meantime you have a perfectly good work around
> by creating explicit instances before calling the function:
>
> { string temp = "Hello World";
> Print (temp);
> }
>
> Both works and highlights the fact that you are 'cheating'.
> Many would think that was good coding practice; make
> explicit the places where you are walking on a knife edge.

And "many more", whoever they are, would immediately question why you
were introducing this variable named temp, giving it a meaningful value,
letting a function do something with it, but then never acting on the
result. I don't think your version is any clearer; quite the contrary,
I'm afraid. If I read something using that idiom in a code review, I'd
immediately wonder what was missing.

Regards,
Chris

Kevlin Henney

unread,
Aug 17, 2001, 10:59:58 AM8/17/01
to
In article <9ldp0t$85j6d$1...@ID-3706.news.dfncis.de>, Markus Schaaf
<m.schaaf.e...@gmx.de> writes
>"Kevlin Henney" <kev...@curbralan.com> wrote:
>
>> const string s = "...";
>> Print(s); // as if: Print(string(s));
>>
>> In other words, a non-const string reference is expected but a const
>> string is provided. A direct binding is not possible, but there would be
>> a conversion from a const string to a non-const string resulting in the
>> introduction of a temporary.
>
>And this is the only thing that the programmer could have
>intended: call "Print" but don't modify "s", because it is
>"const".

Really? I, like others, would have assumed that the programmer had made
a mistake.

>Please remember that this code will not work with
>a standard conforming compiler. So there could be really no
>other interpretation of this line of code.

Good! Having worked on compilers that support non-const reference
binding, I can say from experience that the standard did the right
thing. The programmer was generally in error, but thanks to disallowing
such bindings they can now be in error at compile time rather than at
runtime.

>Of course, you might say that allowing new contructs may be
>dangerous. Yes, that's true. But there is much more in C++
>which is potentially dangerous.

If I can summarise what you may have inadvertently said here: Because
C++ already has a lot of dangerous features, it logically makes more
sense to pursue further dangerous features rather than safe ones :-}

I think you might want to hit the "Refresh" on your wording! :->

Kevlin
____________________________________________________________

Kevlin Henney phone: +44 117 942 2990
mailto:kev...@curbralan.com mobile: +44 7801 073 508
http://www.curbralan.com fax: +44 870 052 2289
Curbralan: Consultancy + Training + Development + Review
____________________________________________________________

Markus Schaaf

unread,
Aug 17, 2001, 11:04:36 AM8/17/01
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote:

> mytype const& foo (mytype & mtr) {
> // do work
> return mtr;
> }
>
> Is going to be problematical as the compiler (possibly only seeing the
> decl) will now almost certainly destroy the temporary early.

IIRC the Standard states that lifetime of temporaries lasts till
the end of a complete statement. Your compiler would be defective.
(OTOH I don't like functions as the one you've sketched, because
these perform implicit upcasts if used with derived classes.)

However, I completely agree with James Kanze, who explained the
real problem you are trying to by-pass is not about temporaries
and references but implicit conversions. To my mind there are
easy ways around all the possible problems you and others pointed
out. This thread's topic rather seems to be religion than
programming, but these are somehow the same. ;-) The best we can
do is to agree to disagree.

Yours sincerely

Dave Harris

unread,
Aug 17, 2001, 11:06:50 AM8/17/01
to
francis.g...@ntlworld.com (Francis Glassborow) wrote (abridged):

> And the problem (certainly for this example) does not arise if the code
> is written correctly.

Several times you have suggested the temporary problem be worked around by
giving the temporary a name. This works, of course, but it is onerous. It
is much nicer to write:

Matrix a, b, c, d, e;
Matrix f = a + b + c*d - e;

then to write:

Matrix a,b,c,d,e;
Matrix temp1 = c * d;
Matrix temp2 = temp1 + b;
Matrix temp3 = temp2 + a;
Matrix f = temp3 - e;

I think if we require that temporaries be named, we lose most of the
benefit of operator overloading. In effect we lose the ability to write
rich expressions. Every expression results in a temporary. Restrictions on
temporaries are restrictions on expressions, and restrictions on
expressions hurt expressiveness.

Another issue is that naming a temporary extends its lifetime. Eg consider
the natural:

vector<int> v;
//...
v.swap( vector<int>( v ) );

to reduce a vector's capacity. If we name the temporary:

vector<int> temp( v );
v.swap( temp );

then old vector memory will remain allocated until the end of the scope.
This has efficiency implications. Also, we have to think of a name for the
variable. It shouldn't *need* a name. We do not intend to refer to it
again. Unnecessary names obscure the code.

Another issue is consistency. For example, this:

vector<int>( v ).swap( v );

is permitted so it is surprising that the original version is forbidden.
Such arbitrary rules make the language trickier to learn and use.
Admittedly this provides us with a workaround for the vector problem, but
it clearly *is* a workaround. There is nothing inherently ill-conceived
about the original code.


> If you want a language change, produce an example where well-designed
> code benefits from allowing temporaries to bind to nc refs.

My usual example is the "pilfer" idiom, where arguments are passed as
non-const references to avoid copying and to allow their internal memory
to be reused.

For example, we might have a type TempMatrix which is only used for
intermediate temporaries and which supports pilfering.

class TempMatrix {
public:
TempMatrix( TempMatrix & );
TempMatrix( const Matrix & );
};
class Matrix {
public:
Matrix( TempMatrix & );
//...
};

TempMatrix operator+( TempMatrix &lhs, const Matrix &rhs );
TempMatrix operator-( TempMatrix &lhs, const Matrix &rhs );
TempMatrix operator*( TempMatrix &lhs, const Matrix &rhs );
//...

Matrix a, b, c, d, e;
Matrix f = a + b + c*d - e;

A Matrix can be converted into a TempMatrix by copying. A TempMatrix can
be converted into a Matrix without copying. Client code does not mention
TempMatrixes explicitly; they are created behind the scenes by expressions
and converted into normal Matrixes on final assignment. This ensures there
is never more than one outstanding reference to a TempMatrix - they are
"once" types. The aim is to avoid memory allocations by "pilfering" memory
from temporary objects which won't miss it because they are about to be
destroyed anyway. Eg:

// Destructive copy - does no memory allocation. Inline, so
// should produce very efficient code.
inline TempMatrix::TempMatrix( TempMatrix &rhs ) : data(rhs.data)
rhs.data = 0; // Ensure rhs can be destroyed cleanly.
}

TempMatrix operator+( TempMatrix &lhs, const Matrix &rhs ) {
TempMatrix result( lhs ); // No memory allocation.
result += rhs; // No memory allocation.
return result; // No memory allocation.
}

See previous discussions for more. I expect searching for "pilfer" will
turn them up.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Dave Harris

unread,
Aug 17, 2001, 11:07:52 AM8/17/01
to
francis.g...@ntlworld.com (Francis Glassborow) wrote (abridged):
> mytype& foo (mytype & mtr) {
> // do work
> return mtr;
> }
>
> Now, under the proposed modification, that creates something very
> surprising and potentially very dangerous (to writing reliable code).

Why?

All the problems I see are independent of the const issue. Eg:

const int &demo( const int &i ) {
return i;
}

void test() {
const int &j = demo( 42 );
cout << j;
}

Here j becomes attached to the temporary created from 42. The temporary is
destroyed at the end of the full expression, so the final line yields
undefined behaviour. This kind of thing is dangerous whether or not we
allow binding to non-const. I don't see the relevance to the current
discussion.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Marco Manfredini

unread,
Aug 17, 2001, 11:10:22 AM8/17/01
to
"Chris Newton" <chris...@no.junk.please.btinternet.com> wrote in
news:9lel97$kvv$1...@plutonium.btinternet.com:

> Marco Manfredini <ma...@technoboredom.net> wrote...
>> For me, the rule tries to solve a problem with the
>> wrong means. Temporaries are not const, but you
>> cannot name them without ending with a const
>> reference. It looks like there is too much pushed
>> into it, to make the argument generation safe
>> enough. By the same time it creates annoying
>> phaenomenons as in:
>>
>> class A{};
>> class Q{public: void foo() {}};
>> int main()
>> {
>> Q().foo(); // ok!
>> A &a=Q(); // not ok!
>> a.foo(); // pffft.
>> }
>
> Unfortunately, that's a prime example of why the rule is there in the
> first place. The statement
> a.foo();
> above acts on a temporary that no longer exists, which is patently
> undefined behaviour (except that, of course, this situation doesn't
> happen in standard C++, because it can't).
>

I object. If a temporary is bound to a (stack scoped) reference, then
the lifetime of the temporary is extended to the lifetime of the
reference

So this is legal & works:

class A{};
class Q{public: void foo() const {}};
int main()
{
const A &a=Q(); //
a.foo(); //
}

It can be seen as if the compiler would rewrite it to:

class A{};
class Q{public: void foo() const {}};
int main()
{
Q temp_q=Q();
const A &a=temp_q
a.foo(); //
}

Regards
--
Marco

"Chapter 25 deals with the generalized subroutines for automatically
transforming lemmings into gold."

Anthony Williams

unread,
Aug 17, 2001, 11:11:06 AM8/17/01
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:kYlcaKAp$7e7...@ntlworld.com...

> In article <9lft2t$96td5$1...@ID-49767.news.dfncis.de>, Anthony Williams
> <ant...@nortelnetworks.com> writes
> >Template forwarding functions. The following is insufficient for use with
> >temporaries, as T& will never deduce to be "const X&" for a temporary.
> >
> >template<typename FunctionType,typename T>
> >void functionForwarder(FunctionType f, T& t)
> >{
> > f(t);
> >}
> That is fine as long as f() does not attempt to modify t. That is as it
> should be IMO.
> >
> >void myfunc(int i);
> ah, I see, you want to use it with a function that takes an argument by
> value.

It doesn't matter what type the forwarded-to function is, since the template
deduction doesn't work on the forwarding function.

struct X
{
X(const int& i);
};
struct MyFunc
{
void operator()(const X&);
} myfunc;

would serve as a suitable alternative declaration of "myfunc" for this case.

I agree with you on the issue regarding literals, but that was not my point.
I used an integer constant here as an example of a temporary, but the same
applies to ALL temporaries.

void func2(const std::string&);
functionForwarder(func2,std::string("hello"));

doesn't work either, and would be fixed by relaxing the
no-non-const-ref-to-temporary rule.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer

Gabriel Dos Reis

unread,
Aug 17, 2001, 12:39:53 PM8/17/01
to
bran...@cix.co.uk (Dave Harris) writes:

| francis.g...@ntlworld.com (Francis Glassborow) wrote (abridged):
| > And the problem (certainly for this example) does not arise if the code
| > is written correctly.
|
| Several times you have suggested the temporary problem be worked around by
| giving the temporary a name. This works, of course, but it is onerous. It
| is much nicer to write:
|
| Matrix a, b, c, d, e;
| Matrix f = a + b + c*d - e;

But in that case, do the function operator arguments need to be
non-const references?

[...]

| vector<int> v;
| //...
| v.swap( vector<int>( v ) );
|
| to reduce a vector's capacity. If we name the temporary:
|
| vector<int> temp( v );
| v.swap( temp );
|
| then old vector memory will remain allocated until the end of the scope.

Oh, that one is already handled in current C++

template<typename T>
void reduce_capacity(std::vector<T>& v)
{


vector<int> temp( v );
v.swap( temp );
}

reduce_capacity(v);

I bet the main code gains in readability.


--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Chris Newton

unread,
Aug 17, 2001, 2:45:23 PM8/17/01
to
Francis Glassborow <francis.g...@ntlworld.com> wrote...

> Chris Newton <chris...@no.junk.please.btinternet.com> writes
> >Francis Glassborow <francis.g...@ntlworld.com> wrote...
> > > When I pass by reference it is because I want
> > > the called function to modify the original.
> >
> > Nope, it's because the person who wrote the function
> > you're calling decided to take a reference parameter.
> > What you want, as the person calling it, is unfortunately
> > completely irrelevant.
>
> But I have already provided a perfectly reasonable work
> round where the designer of the function is incompetent,
> or where you are willing to trash the use of the parameter
> as an out parameter

And I disagree with that workaround, for the reasons I noted at the
time.

> > Herein lies the flaw with most of the arguments in favour
> > of status quo on this thread. They presuppose that you
> > are working with an interface over which you have control.
> > Frequently, this is not the case, and it's then that the ability
> > to pass a temporary as a non-const reference can be useful.
>
> Then write:
>
> {
> mytype mt(/*...*/);
> foo(mt);
> }

And also
{
Coordinate ignoredX1;
Coordinate ignoredY1;
Coordinate ignoredX2;
Coordinate ignoredY2;
Coordinate X3;
Coordinate Y3;
GetTriangleVertices(ignoredX1, ignoredY1, ignoredX2, ignoredY2, X3,
Y3);
}
and so on? This approach rapidly gets confusing and unwieldy.

Obviously the above is a somewhat contrived example, but I sometimes
have to work with classes that define methods with multiple references
for "out" parameters, assuming you will discard what you don't want.
Yes, it could be a better designed interface, but there's nothing I can
do about that. Your approach would become cryptic and result in
functions, say, five times longer than they need to be in several cases
I've dealt with. On the other hand, changing the rule about temporaries,
and instead addressing the deeper issues of implicit behaviour (which
are the real problem here anyway) would be more constructive, IMHO.

[...]

> You insist on wanting an entirely new type of diagnostic -
> one applied to well formed code. Compilers can issue
> warnings, and often do, before carrying out the intent of
> ill-formed code. But having required diagnostics on well
> formed code is an entirely different thing.

It's also what everybody does. If the standard doesn't represent an
agreed variation of what people actually do, it has no value anyway. I
sometimes think the standards committee forget this.

While we're on the subject, I personally find the standard's whole
treatment of compiler output very unhelpful. No-one in the real world
talks of "diagnostics". They talk of "errors" and "warnings" (possibly
at multiple levels). I don't know a single compiler that's an exception
to this, and I've never met someone who used the term "diagnostic"
instead, excepting those on the standards committee or people discussing
the standard. Such guidance as the standard does provide is somewhat
uneven, with clear guidelines being given in some places, but no
apparent criteria for what those places are to be.

So, given that a revision of the standard is coming up, may I
respectfully suggest that the standards committee should document what
is actually the current standard, i.e., use the terms "error" and
"warning" where appropriate, and, following clear guidelines, define
where (at a minimum) these are required. The case for errors is clear,
and given the standards committee's greater awareness of thorny issues
and potential mistakes, I think the case for mandated warnings is clear
as well.

> > It's not like C++ is a language that chooses safety over
> > flexibility in most other circumstances, after all. Quite
> > the contrary in fact; indeed, one could argue that much
> > of its success is due to the fact that it *doesn't* stop me
> > doing apparently silly things, if I deliberately choose to
> > do so and have my reasons. I've never understood why
> > an anti-philosophy decision was made in this case.
>
> Some of us want to reduce these problems, you seem to
> want to increase them. Some of us want a safer C++.

Not at all. I want a safer C++ as well, but *never* at the expense of
letting me do what I want to because someone else thinks it's a bad
idea. If I wanted to program in Java, I'd program in Java.

Regards,
Chris

Kevlin Henney

unread,
Aug 17, 2001, 3:19:34 PM8/17/01
to
In article <9lh2d2$man$1...@uranium.btinternet.com>, Chris Newton
<chris...@no.junk.please.btinternet.com> writes

>Too bad. Since about 90% of the code I work with is badly written, even
>if I and the language I use are perfect, I'm still screwed if I adopt
>that attitude.
[...]

>I can't. They were contractors, and they left the company before I even
>joined. Do you not see the simple real-world problem here? I do not
>have control of most of the "bad code".

Yes, I believe I can see the real world problem here, but perhaps you
have missed it: you want us to change the language rules to solve
organisational and project management problems. I would suggest that
this is somewhat beyond the remit of the ISO C++ standard! ;-)

>Furthermore, while I could theoretically "fix" some of the poor
>interfaces I work with, I will not be authorised to do so. We, and our
>clients, have invested months testing the application. Any change in a
>given area immediately invalidates some of those tests and leads to the
>cost of retesting to make sure nothing's been broken. At present, it's
>not broken and is known to work, it's just not as good as it could have
>been. That does not justify changing it.

So instead of changing the code that depends on the C++ platform, you
want to change the platform to fit the code? Don't call us, we'll call
you ;->

Kevlin
____________________________________________________________

Kevlin Henney phone: +44 117 942 2990
mailto:kev...@curbralan.com mobile: +44 7801 073 508
http://www.curbralan.com fax: +44 870 052 2289
Curbralan: Consultancy + Training + Development + Review
____________________________________________________________

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 17, 2001, 6:13:39 PM8/17/01
to
"Chris Newton" <chris...@no.junk.please.btinternet.com> writes:

[...]

| > You insist on wanting an entirely new type of diagnostic -
| > one applied to well formed code. Compilers can issue
| > warnings, and often do, before carrying out the intent of
| > ill-formed code. But having required diagnostics on well
| > formed code is an entirely different thing.
|
| It's also what everybody does.

Really? Who are "everbody"?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 17, 2001, 7:22:36 PM8/17/01
to
In article <memo.20010817...@brangdon.madasafish.com>, Dave
Harris <bran...@cix.co.uk> writes

>All the problems I see are independent of the const issue. Eg:
>
> const int &demo( const int &i ) {
> return i;
> }
>
> void test() {
> const int &j = demo( 42 );
> cout << j;
> }
>
>Here j becomes attached to the temporary created from 42. The temporary is
>destroyed at the end of the full expression, so the final line yields
>undefined behaviour. This kind of thing is dangerous whether or not we
>allow binding to non-const. I don't see the relevance to the current
>discussion.

Well, I am not so sure. The rules are different for temporaries bound to
const references. What I am unsure of is the result of chaining together
const refs as the above does.


Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Aug 17, 2001, 7:42:40 PM8/17/01
to
In article <9lh2d2$man$1...@uranium.btinternet.com>, Chris Newton
<chris...@no.junk.please.btinternet.com> writes
>I can't. They were contractors, and they left the company before I even
>joined. Do you not see the simple real-world problem here? I do not
>have control of most of the "bad code".
>
>Furthermore, while I could theoretically "fix" some of the poor
>interfaces I work with, I will not be authorised to do so. We, and our
>clients, have invested months testing the application. Any change in a
>given area immediately invalidates some of those tests and leads to the
>cost of retesting to make sure nothing's been broken. At present, it's
>not broken and is known to work, it's just not as good as it could have
>been. That does not justify changing it.
>
>Given these two basic problems, I have to work with things as they are.
>The current rule is not helping me.

I can think of no other engineering discipline in which a proposal to
make something less safe on such grounds would not be laughed out of
court. I would think the ability to say to management that this code is
so bad that it will not compile with certified (when we have such
things) correct compilers would be an advantage. If we all adopt the
attitude that we will fix the language rather than the code, we might as
well give up any pretensions to quality.

I know that the real world sometimes requires us to compromise, but that
is not an excuse for dumping that compromise on everyone else. We do not
change the rules for electrical wiring because there are incompetent
electricians that confuse neutral and earth, or who put wires into walls
diagonally and unshielded. We sack them, and if their work causes injury
we sue them for negligence.


Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Eric Tetz

unread,
Aug 18, 2001, 9:51:36 AM8/18/01
to
"Marco Manfredini" <ma...@technoboredom.net> wrote:
> If a temporary is bound to a (stack scoped) reference, then the lifetime of
> the temporary is extended to the lifetime of the reference
>
> So this is legal & works:
>
> class A{};
> class Q{public: void foo() const {}};
> int main()
> {
> const A &a=Q(); //
> a.foo(); //
> }

I'm genuinely confused by these examples you are giving! I don't see how you
can call any of them legal - how can an A& ever refer to a Q?. Obviously, I
missed a major part of this discussion, I just can't figure out what it is...

As far as the "bound to a (stack scoped) reference", whjat does 'stack scoped'
mean? Is the following not legal?

class Q{public: void foo() const {}};

const Q& q = Q();
int main()
{
q.foo();
}

Curious,
Eric

Markus Schaaf

unread,
Aug 18, 2001, 10:01:00 AM8/18/01
to
"Kevlin Henney" <kev...@curbralan.com> wrote:

> >> const string s = "...";
> >> Print(s); // as if: Print(string(s));

> >And this is the only thing that the programmer could have


> >intended: call "Print" but don't modify "s", because it is
> >"const".
>
> Really? I, like others, would have assumed that the programmer had made
> a mistake.

IMO you are too quick with judgements like this. Now this code is
supposed to be a mistake, but yesterday it was a mistake that
"Print" takes a non-const reference. :) I wouldn't want to decide
what's a mistake seeing only two lines of code. And I really hate
it if that decision is hard-wired. It's that "I know better" sort
of thinking, that makes life harder sometimes, especially if it
comes to computers. Last time I was about to buy a ticket for a
delayed train I couldn't do so, because the programmer has
decided, that it is a mistake to buy a ticket for a train that
had left.

> If I can summarise what you may have inadvertently said here: Because
> C++ already has a lot of dangerous features, it logically makes more
> sense to pursue further dangerous features rather than safe ones :-}

That's an exaggeration, but there's some truth in it.

Don't get me wrong: I don't want that code at the top of this
posting to compile, although my first sentences may read
contrary. Temporaries originating from implicit conversions
shouldn't be bound to non-const references. And of course the
behaviour of well-formed programms must not be altered by a
possible change allowing that "temporary non-const stuff". But
don't give me poor excuses why something like this would be
impossible. It isn't. Just say: "I don't like it.", and perhaps
ask yourself why. And consider "mutable" and non-const member
functions.

Yes, and there was that compiler, which had some kind of feature
which didn't work well. But that is not what we were talking
about.

Yours sincerely

Francis Glassborow

unread,
Aug 18, 2001, 1:12:36 PM8/18/01
to
In article <9ljhq6$ogb$1...@neptunium.btinternet.com>, Chris Newton
<chris...@no.junk.please.btinternet.com> writes

>So, given that a revision of the standard is coming up, may I
>respectfully suggest that the standards committee should document what
>is actually the current standard, i.e., use the terms "error" and
>"warning" where appropriate, and, following clear guidelines, define
>where (at a minimum) these are required. The case for errors is clear,
>and given the standards committee's greater awareness of thorny issues
>and potential mistakes, I think the case for mandated warnings is clear
>as well.

There is an excellent reason for the Standards terminology. There is no
such thing as a warning as far as the Standard is concerned (and I am
not sure how many other languages support such a concept). A piece of
code is

1) Correct, and the Standard never requires any form of message in such
a case. There are quite a few people who would violently object to any
change to this because they have coding standards that require that code
is compiled free of error and warning messages.

2) Incorrect, and the 'error' is one that is required to be 'diagnosed'
though after that the compiler is free to continue if it can.

3) Incorrect, and diagnosis of the error cannot be reasonably diagnosed
in all cases, no diagnostic is required (though giving one is not
forbidden).

The word 'diagnostic' is used exactly because many compiler writers
would be very unhappy with the term 'error' applied when their compiler
supports an extension that supports the code in question. Why should it
have been deemed an 'error' for a compiler to support accented letters
in variable names? Clearly this is a portability problem, and will be an
error for any compiler that does not provide such support, but for those
that do, it will be no more than a warning (i.e. you have used a non-
portable construct in your code). The requirement that an ill-formed TU
need only generate a single diagnostic is exactly designed to support
such extensions without generating reams of messages that obscure
serious faults.

The only fault I find with the Standard's required diagnostics is that I
believe that some 'undefined behaviour' could be moved to ill-formed,
diagnostic required.

Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Chris Newton

unread,
Aug 18, 2001, 3:06:10 PM8/18/01
to
Kevlin Henney <kev...@curbralan.com> wrote...

> Yes, I believe I can see the real world problem here, but
> perhaps you have missed it: you want us to change the
> language rules to solve organisational and project
> management problems.

When those problems are themselves caused by the language, yes.

> I would suggest that this is somewhat beyond the remit
> of the ISO C++ standard! ;-)

I respectfully disagree. The protection features in C++, separating
interface from implementation and so on, are Good Things, and I wouldn't
want to see the philosophy changed. However, they also, by their nature,
introduce restraints on the programmer. Those restraints are the direct
cause of these problems (in this case, because I can't modify the bad
interface). What the rule in question does is prevent me, the
programmer, from dealing with those restraints in the most obvious and
convenient way.

[...]

> So instead of changing the code that depends on the C++
> platform, you want to change the platform to fit the code?

No, I want you to change the platform so *I* can make the code fit, if I
make an informed decision to do so.

At the moment, C++ decides that binding a non-const ref to a temporary
is wrong. Clearly, looking at this thread, that is not always the case,
and several legitimate uses for the technique have been cited. This rule
is so obviously contrary to the normal philosophy of the language that I
find it incredible that the standards committee are here defending it.

Every single counterexample or workaround I have seen on this thread is
a subjective decision by someone about how *they* personally think the
problem should be solved. If they choose to do it that way, that's
absolutely fine with me, but please don't force others to do it the same
way. We're allowed to have more than one correct solution to a problem
these days...

> Don't call us, we'll call you ;->

Sorry, but I felt obliged to call back on this one. :-)

Regards,
Chris

Dave Harris

unread,
Aug 18, 2001, 6:24:35 PM8/18/01
to
dos...@cmla.ens-cachan.fr (Gabriel Dos Reis) wrote (abridged):

> But in that case, do the function operator arguments need to be
> non-const references?

See later in the article you are replying to. The results of the operators
are instances of TempMatrix, which want to be passed by non-const
reference to the next operator. By reference, so that copying them is
fast. Non-const, so that their memory can be extracted and used for the
return result.


> Oh, that one is already handled in current C++

See later in the article you are replying to, for my comments on that
workaround.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Dave Harris

unread,
Aug 18, 2001, 7:08:37 PM8/18/01
to
francis.g...@ntlworld.com (Francis Glassborow) wrote (abridged):
> What I am unsure of is the result of chaining together const refs
> as the above does.

Here is a more complex example, which I think is clearer.

static int stashed;
const int &stash( const int &i );

void test() {
const int &j = stash( 42 );
stashed = 54;
cout << j;
}

const int &stash( const int &i ) {
stashed = i;
if (rand())
return stashed;
else
return i;
}

Consider test(). The compiler cannot assumed the temporary referred to by
j is the one created from 42, because sometimes it isn't. (Also, in
general, the body of stash() may not be available.) Therefore the compiler
has no good reason to extend the lifetime of the temporary. It must
destroy it at the end of the full expression, as usual.

The compiler has to leave j alone, too. It cannot create a new temporary,
bind j to it, and extend its lifetime, because j might be bound to the
static stashed, in which case it must reflect changes to that variable.
(It would be an outrageous thing to do anyway, eg if this were a type with
constructors.) J must be bound to whatever the function returns. Sometimes
it will be bound to the temp which is about to be destroyed.

It seems to me the above code results in undefined behaviour when rand()
returns 0. We must be *very* careful about returning references to things
whose lifetimes we are unsure about. This is true whether or not the
references are const. Your example merely illustrated this general
problem.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Dave Harris

unread,
Aug 18, 2001, 7:09:14 PM8/18/01
to
chris...@no.junk.please.btinternet.com (Chris Newton) wrote (abridged):

> So, given that a revision of the standard is coming up, may I
> respectfully suggest that the standards committee should document what
> is actually the current standard, i.e., use the terms "error" and
> "warning" where appropriate, and, following clear guidelines, define
> where (at a minimum) these are required. The case for errors is clear,
> and given the standards committee's greater awareness of thorny issues
> and potential mistakes, I think the case for mandated warnings is clear
> as well.

I agree with Francis Glassborow on this point. To my mind, a warning is
equivalent to an error. I insist that my programs compile with neither.
This can mean either rewriting to avoid the questionable code, or else
figuring out how to disable the warning. In the latter case it's usually a
stupid warning so I'll want to disable it globally.

Code is either right or wrong. There is some scope for the compiler
saying, "are you sure", but if I am sure then the compiler should shut up.
Mandated warnings, which cannot be disabled, only make sense for code
which should never be written. In which case it should be an error.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 18, 2001, 7:17:30 PM8/18/01
to
bran...@cix.co.uk (Dave Harris) writes:

| dos...@cmla.ens-cachan.fr (Gabriel Dos Reis) wrote (abridged):
| > But in that case, do the function operator arguments need to be
| > non-const references?
|
| See later in the article you are replying to.

I was it. I was not convinced, that is why I replied.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 18, 2001, 7:40:56 PM8/18/01
to
"Chris Newton" <chris...@no.junk.please.btinternet.com> writes:

[...]

| This rule


| is so obviously contrary to the normal philosophy of the language that I
| find it incredible that the standards committee are here defending it.

In this thread you have, at several times, stated things about the
"philosophy of C++". Would you pretend to understand better than the
creator of C++, what "the philosophy of C++" is?

| Every single counterexample or workaround I have seen on this thread is
| a subjective decision by someone about how *they* personally think the
| problem should be solved. If they choose to do it that way, that's
| absolutely fine with me, but please don't force others to do it the same
| way.

Either way you take it -- allowing or not allowing temporary bound to
non-const reference -- one has to make a choice, so what?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Schaaf

unread,
Aug 18, 2001, 8:31:00 PM8/18/01
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote:

> Then write:
>
> {
> mytype mt(/*...*/);
> foo(mt);
> }

Ok, but that workaround becomes a pain in the neck if you have
to do this often, especially with more complex expressions,
because you must split one line of code into different blocks
and possibly nested if-statements (if that mentioned expression
contains conditional operators).

Michael Sullivan

unread,
Aug 18, 2001, 10:12:04 PM8/18/01
to
Markus Werle <mar...@lufmech.rwth-aachen.de> wrote:

> My impression is that the non-const-reference discussion is similar
> to the multiple inheritance stuff: the OO-purists say "no" (like in Ada)
> and the specialists make heavy use of it when it enters the standard
> (producing better OO-designs than the purists)

Okay this is off the existing topic, but WTF? I was out of programming
for most of the evolution of C++ and OO, but it strikes me that you
*can't* represent certain kinds of important object relationships
without multiple inheritance. When I read that multiple inheritance had
detractors and took a long time to make it into the standard, I assumed
it was due to implementation problems. I would have thought OO
"purists" would consider multiple inheritance an absolute requirement.

I'm intuiting "OO-purist" to mean someone whose primary concern is with
the ability to accurately (and intuitively to the user) model problem
spaces with language objects. It seems to me that multiple inheritance
is a really important tool for that. Is there some concern of OO
purists that I'm missing, or some way of modeling "is a" relationships
that can account for sets of objects that do not fit neatly into a tree
of specificity hierarchy?


Michael

Dave Harris

unread,
Aug 19, 2001, 1:33:48 PM8/19/01
to
dos...@cmla.ens-cachan.fr (Gabriel Dos Reis) wrote (abridged):
> | dos...@cmla.ens-cachan.fr (Gabriel Dos Reis) wrote (abridged):
> | > But in that case, do the function operator arguments need to be
> | > non-const references?
> |
> | See later in the article you are replying to.
>
> I was it. I was not convinced, that is why I replied.

Well, what do you think was wrong with my design? Unless you actually
highlight where the problem lies, I don't know how to reply to you.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Werle

unread,
Aug 20, 2001, 4:26:12 PM8/20/01
to
Francis Glassborow <francis.g...@ntlworld.com> writes:

> [...]


> I can think of no other engineering discipline in which a proposal to
> make something less safe on such grounds would not be laughed out of
> court. I would think the ability to say to management that this code is
> so bad that it will not compile with certified (when we have such
> things) correct compilers would be an advantage. If we all adopt the
> attitude that we will fix the language rather than the code, we might as
> well give up any pretensions to quality.

I feel like Chris wanted to say that the root for this problem lies in the
asymmetry of C++ rules occuring for non-const references and that the rules
really need a fix. The fact that too many compilers can deal with it properly
(though non-standard) should drive us to a rethink of our paradigms.

By now I can see there were good reasons not to allow it without
restriction. But I still have not catched the reason for disallowing it in the
case where implicit conversions are forbidden.

Maybe I missed the point in some other post, but please, for me (the stupid)
explain it slowly with comments on what happens. I always felt lifetime
issues
are the the most hard to understand but most important thing to learn in C++,
so
again and again until I catch it:

If implicit conversions were disallowed for non-const references
like it is for template arguments, is there anything that will go wrong?
(well I mean besides the fact that const references are not safe either
as I learned from another brach in this thread)

It would be intuitive to state a rule like: "If things can break up by
accident
The language disables implicit conversions".


> > I know that the real world sometimes requires us to compromise, but that
> is not an excuse for dumping that compromise on everyone else. We do not
> change the rules for electrical wiring because there are incompetent
> electricians that confuse neutral and earth, or who put wires into walls
> diagonally and unshielded. We sack them, and if their work causes injury
> we sue them for negligence.

I do not think the issue is compromise but the strong will to heal a (possibly
not existing) defect in C++ rules. Please do not attack that opinion by
further
electrician examples (yes, we know by now that You think it is dangerous) but
lead us all back on the right way by providing beat-it-all _arguments_. If
others are not convinced by what You already stated: refine until
convergence. Yes, I urge You to do so. Where did we put the wires diagonally?
I
really want to know if it as bad as stated.

Markus


--
What do You think: is Pluto a Planet?

Eugene Karpachov

unread,
Aug 20, 2001, 5:27:10 PM8/20/01
to
17 Aug 2001 18:13:39 -0400 Gabriel Dos Reis :

>| It's also what everybody does.
>
>Really? Who are "everbody"?

Developers of gcc - surprise, surprise. I never saw word "diagnostics" in gcc
output, only words "error" and "warning".

--
jk

Francis Glassborow

unread,
Aug 20, 2001, 7:03:18 PM8/20/01
to
In article <tgn14vj...@tresca.lufmech.RWTH-Aachen.DE>, Markus Werle
<mar...@lufmech.rwth-aachen.de> writes

>I do not think the issue is compromise but the strong will to heal a
(possibly
>not existing) defect in C++ rules. Please do not attack that opinion by
>further
>electrician examples (yes, we know by now that You think it is dangerous) but
>lead us all back on the right way by providing beat-it-all _arguments_. If
>others are not convinced by what You already stated: refine until
>convergence.

I do not need to convince anyone, because my position is the status quo.
It is also the position maintained by those responsible for the
language. If you want change the onus is on you to provide a convincing
case for doing so.

Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Bob Bell

unread,
Aug 20, 2001, 9:05:44 PM8/20/01
to
> > Then write:
> >
> > {
> > mytype mt(/*...*/);
> > foo(mt);
> > }
>
> Ok, but that workaround becomes a pain in the neck if you have
> to do this often, especially with more complex expressions,
> because you must split one line of code into different blocks
> and possibly nested if-statements (if that mentioned expression
> contains conditional operators).

The Facade pattern will take care of that. Just make a new interface
which hides the const-incorrectness of the API you cannot modify:

// From some header which you cannot change:
void ConstIncorrectVersion(mytype&);

// From your new Facade interface:
void ConstCorrectVersion(const mytype& arg)

{
mytype mt(arg);

ConstIncorrectVersion(mt);
}

Bob Bell

Gabriel Dos Reis

unread,
Aug 21, 2001, 1:10:07 AM8/21/01
to
j...@steel.orel.ru (Eugene Karpachov) writes:

| 17 Aug 2001 18:13:39 -0400 Gabriel Dos Reis :
| >| It's also what everybody does.
| >
| >Really? Who are "everbody"?
|
| Developers of gcc - surprise, surprise. I never saw word "diagnostics" in
gcc
| output, only words "error" and "warning".

Fair enough. But GCC does not constitute "everybody".

I'm pretty sure that the titles of the relevant sections speaking
of how those "error" and "warning" in GCC manual (which you should
have already read) are formatted and their meanings use the word
"diagnostic". Remember that a diagnostic is what the documentation
says it is.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Markus Werle

unread,
Aug 21, 2001, 3:11:00 PM8/21/01
to
Francis Glassborow <francis.g...@ntlworld.com> writes:

> I do not need to convince anyone, because my position is the status quo.

I just hoped You share the deeper insight to the why and why not
with others. Anyway, I just found out I did not get it right
even for the const reference, so I am really confused now.

Again: please, could You or anybody else in this forum
explain why a reference to a non-const
can break up everything even for the case where implicit
conversions are disallowed.

regards,

Markus

James Kanze

unread,
Aug 21, 2001, 9:27:07 PM8/21/01
to
"Chris Newton" <chris...@no.junk.please.btinternet.com> wrote in
message news:<9ljhq6$ogb$1...@neptunium.btinternet.com>...

> While we're on the subject, I personally find the standard's whole
> treatment of compiler output very unhelpful. No-one in the real
> world talks of "diagnostics". They talk of "errors" and "warnings"
> (possibly at multiple levels). I don't know a single compiler that's
> an exception to this, and I've never met someone who used the term
> "diagnostic" instead, excepting those on the standards committee or
> people discussing the standard. Such guidance as the standard does
> provide is somewhat uneven, with clear guidelines being given in
> some places, but no apparent criteria for what those places are to
> be.

I suspect that the committee intentionally avoided the words error and
warning because of this. In particular (at least in the C committee,
but I believe that the sentiment of the C++ committee was the same),
it was the expressed intent that a compiler be allowed to continue to
compile an illegal program, and produce an executable, if it wished.
And in fact, every compiler I know does, in certain cases:
anachronisms (warning: this code is illegal according to the standard,
but it worked with our earlier versions, so we'll let it by),
extensions (warning: the C++ does not allow $ in a symbol, but we do
as an extension), etc.

The important thing is that the implementation document this: all
errors, and warnings a, b, and c are to be considered diagnostics in
the sense of the standard.

> So, given that a revision of the standard is coming up, may I
> respectfully suggest that the standards committee should document
> what is actually the current standard, i.e., use the terms "error"
> and "warning" where appropriate, and, following clear guidelines,
> define where (at a minimum) these are required. The case for errors
> is clear, and given the standards committee's greater awareness of
> thorny issues and potential mistakes, I think the case for mandated
> warnings is clear as well.

What is the difference between a warning and an error? For most
people, I think, it is simply the message the compiler emits, i.e.,
"Warning: blah, blah blah", or "Error: blah, blah, blah". But I would
strongly oppose this; depending on where I'm working, I would really
prefer "Avertissement: ..."/"Erreur: ..." or "Warnung: ..."/"Fehler
...".

Probably the most important difference (IMHO) with most compilers is
that the return code to the system will be different; an error breaks
the build, a warning doesn't. But requiring this would render C++
unimplementable on OS's which don't support return codes, and make it
illegal to implement the compiler in a language which didn't provide
for return codes.

Another typical difference is that the compiler will produce no output
if there is an error, but will produce output if there are warnings.
In order to require this, however, and still support the above cited
uses, you need three categories of diagnostics: those which are
required to suppress output, those which may not suppress output (your
"required warnings"), and those where the implementation can decide
for itself. It's hard enough to get concensus on the standard as is;
I'd hate to have to argue about these issues as well, given the low
level of importance they have.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

James Kanze

unread,
Aug 21, 2001, 9:31:15 PM8/21/01
to
Francis Glassborow <francis.g...@ntlworld.com> wrote in message
news:<+6J6SJAd...@ntlworld.com>...

> In article <memo.20010817...@brangdon.madasafish.com>, Dave
> Harris <bran...@cix.co.uk> writes
> >All the problems I see are independent of the const issue. Eg:

> > const int &demo( const int &i ) {
> > return i;
> > }

> > void test() {
> > const int &j = demo( 42 );
> > cout << j;
> > }

> >Here j becomes attached to the temporary created from 42. The
> >temporary is destroyed at the end of the full expression, so the
> >final line yields undefined behaviour. This kind of thing is
> >dangerous whether or not we allow binding to non-const. I don't see
> >the relevance to the current discussion.

> Well, I am not so sure. The rules are different for temporaries
> bound to const references. What I am unsure of is the result of
> chaining together const refs as the above does.

The rule is simple. If a temporary is bound to a reference, the
temporary that is bound acquires the lifetime of the reference. That
is all. In this case, 42 acquires the lifetime of the parameter i.
If 42 lasts to the end of the expression, it is only because this rule
can only be invoked to lengthen the lifetime of temporaries, not to
shorten it. What is bound to j is the return value of demo, which
happens to be a reference (and thus an lvalue and not a temporary).
It has no effect whatsoever on the temporary 42.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
Aug 21, 2001, 9:32:01 PM8/21/01
to
"Chris Newton" <chris...@no.junk.please.btinternet.com> wrote in
message news:<9lm44l$is6$1...@neptunium.btinternet.com>...

> At the moment, C++ decides that binding a non-const ref to a
> temporary is wrong. Clearly, looking at this thread, that is not
> always the case, and several legitimate uses for the technique have
> been cited. This rule is so obviously contrary to the normal
> philosophy of the language that I find it incredible that the
> standards committee are here defending it.

The rule predates the committee. When references were first
introduced, the rule didn't exist; you could bind a temporary to any
reference. Empirically, it was found to be an enormous source of
error; enough to require a change breaking existing code. (Not
everything was const-correct at the time.)

It's not a question of trying to protect someone from a potential
error; it's a question of preventing a large number of real errors.

(That doesn't mean that it is the only possible rule. But any
proposal for a change must address the problem.)

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
Aug 21, 2001, 9:32:55 PM8/21/01
to
j...@steel.orel.ru (Eugene Karpachov) wrote in message
news:<slrn9o1n...@localhost.localdomain>...

> 17 Aug 2001 18:13:39 -0400 Gabriel Dos Reis :
> >| It's also what everybody does.

> >Really? Who are "everbody"?

> Developers of gcc - surprise, surprise. I never saw word
> "diagnostics" in gcc output, only words "error" and "warning".

And I've used compiles that never use the word "error" in their
output. If there is output, and it isn't indicated "warning", it
should be treated as an error.

It is fully conform with the intent of the standards committee that
compilers have two types of output: errors and warnings. Both may be
considered diagnostics, and the current standard never requires a
compiler to output the word error.

In the case of g++, of course, while the compiler itself might not
output the word "diagnostic", section 2.6 of the manual starts
"Warnings are diagnostic messages [...]" Obviously, the authors of
g++ are aware of the term.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Tom

unread,
Aug 21, 2001, 9:49:05 PM8/21/01
to
On 21 Aug 2001 15:11:00 -0400, Markus Werle
<mar...@lufmech.rwth-aachen.de> wrote:

>Francis Glassborow <francis.g...@ntlworld.com> writes:
>
>> I do not need to convince anyone, because my position is the status quo.
>
>I just hoped You share the deeper insight to the why and why not
>with others. Anyway, I just found out I did not get it right
>even for the const reference, so I am really confused now.
>
>Again: please, could You or anybody else in this forum
>explain why a reference to a non-const
>can break up everything even for the case where implicit
>conversions are disallowed.

Firstly Gabriel Dos Reis has posted an example of current code that
would silently change meaning if the new binding was allowed. This is
because of overload resolution.

Secondly, many compilers allow the binding as an extension (warnings
are usually issued, and I don't know how overload resolution is dealt
with). If, like Chris Newton, you are working with a broken interface
that you can't fix, then perhaps you should use the extension.

And finally, the non-binding of temporaries to non-const references is
one of the things that causes const correct code to get written. If
the rule was changed, the compiler would silently compile
const-incorrect code causing problems in the future.

Tom

Eugene Karpachov

unread,
Aug 22, 2001, 6:12:49 AM8/22/01
to
21 Aug 2001 21:49:05 -0400 Tom wrote:
>On 21 Aug 2001 15:11:00 -0400, Markus Werle
><mar...@lufmech.rwth-aachen.de> wrote:
>
>>Francis Glassborow <francis.g...@ntlworld.com> writes:
>>
>>> I do not need to convince anyone, because my position is the status quo.
>>
>>I just hoped You share the deeper insight to the why and why not
>>with others. Anyway, I just found out I did not get it right
>>even for the const reference, so I am really confused now.
>>
>>Again: please, could You or anybody else in this forum
>>explain why a reference to a non-const
>>can break up everything even for the case where implicit
>>conversions are disallowed.
>
>Firstly Gabriel Dos Reis has posted an example of current code that
>would silently change meaning if the new binding was allowed. This is
>because of overload resolution.

It is necessary to forbid given example as ambigous. As to change of
existing programs, introduction of a considered rule also has changed value of
some existing programs, however the given rule was entered. Introduction of
new for-loop scope also has changed existing programs, however it has not
prevented to enter it.

>Secondly, many compilers allow the binding as an extension (warnings
>are usually issued, and I don't know how overload resolution is dealt
>with). If, like Chris Newton, you are working with a broken interface
>that you can't fix, then perhaps you should use the extension.

What if someone is working with a broken interface but with strict compiler?

>And finally, the non-binding of temporaries to non-const references is
>one of the things that causes const correct code to get written. If
>the rule was changed, the compiler would silently compile
>const-incorrect code causing problems in the future.

What is const-incorrect in this code:

void f(int& a) {
std::cout << a;
a=std::cout.good();
}

void g() {
int quux();
f(quux());
// Yes, I'm intentionally discarding "returned" value.
}

May be it is bad design, but design is not a subject for standardization.

--
jk

Gabriel Dos Reis

unread,
Aug 22, 2001, 12:01:38 PM8/22/01
to
j...@steel.orel.ru (Eugene Karpachov) writes:

| >Firstly Gabriel Dos Reis has posted an example of current code that
| >would silently change meaning if the new binding was allowed. This is
| >because of overload resolution.
|
| It is necessary to forbid given example as ambigous. As to change of
| existing programs, introduction of a considered rule also has changed value
of
| some existing programs, however the given rule was entered. Introduction of
| new for-loop scope also has changed existing programs, however it has not
| prevented to enter it.

I don't share the view "we broke it once, then there is no reason we
should not break it again".

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Chris Newton

unread,
Aug 22, 2001, 12:25:58 PM8/22/01
to
Gabriel Dos Reis wrote...

> "Chris Newton" <chris...@no.junk.please.btinternet.com> writes:
>
> [...]
>
> | This rule is so obviously contrary to the normal philosophy
> | of the language that I find it incredible that the standards
> | committee are here defending it.
>
> In this thread you have, at several times, stated things
> about the "philosophy of C++". Would you pretend to
> understand better than the creator of C++, what "the philosophy
> of C++" is?

I would never presume to speak for anyone else, including Bjarne
Stroustrup. Actually, I think it's rather sad that the in-crowd have
now resorted to name dropping. I'm sure that if Mr Stroustrup wants to
express his opinion on this thread, he knows how to do so.

However, since you bring it up... My feelings on this issue have been
heavily influenced by comments Bjarne has made (D&E, TC++PL, various
interviews) about the trade-off between language features and language
safety. I suspect that he is thinking of somewhat larger issues when
he discusses this, but I don't see why the principle doesn't apply
here as well.

> | Every single counterexample or workaround I have seen on
> | this thread is a subjective decision by someone about how
> | *they* personally think the problem should be solved. If
> | they choose to do it that way, that's absolutely fine with
> | me, but please don't force others to do it the same way.
>
> Either way you take it -- allowing or not allowing temporary
> bound to non-const reference -- one has to make a choice, so
> what?

One of those choices lets the individual programmer do what is correct
under his or her particular circumstances. The other forces someone
else's idea of "correct" upon them, on the pretence of increasing
safety. I feel, as do some others here, that the wrong decision was
made.

Regards,
Chris

Chris Newton

unread,
Aug 22, 2001, 5:00:40 PM8/22/01
to
tom_u...@hotmail.com (Tom) wrote...

> Firstly Gabriel Dos Reis has posted an example of current
> code that would silently change meaning if the new binding
> was allowed. This isbecause of overload resolution.

One could reasonably argue that any code that actually relies on this
rule to disambiguate is broken already. Furthermore, it is always
possible (and trivial) to rewrite such code in a way that makes the
intent explicit. If the scenario happens often, you could even
automate the fix. Then again, if it happens often, this rule change is
probably a long way down your list of worries. :-(

Incidentally, I think the fact that the future C++ standard will break
some existing code in minor ways is inevitable. If it doesn't,
clearing up irritating idiosyncracis (templates and >>, anyone?) isn't
going to happen, and that would be a shame.

> Secondly, many compilers allow the binding as an extension
> (warnings are usually issued, and I don't know how overload
> resolution is dealt with). If, like Chris Newton, you are
> working with a broken interface that you can't fix, then
> perhaps you should use the extension.

It's not just broken interfaces; that was simply the first example of
a constructive use for the feature that I came up with, since it's
where this thread started. Others have cited further problems with the
status quo elsewhere.

The compilers I use do provide the functionality as a non-standard
extension, and on some projects, we use it all the time. However, in
more than a million lines of code on just this one project, I've never
seen any of the safety issues it's designed to prevent. That's not to
say that they can't happen, just that I think the legitimate concerns
are being massively overhyped by some people here.

> And finally, the non-binding of temporaries to non-const
> references is one of the things that causes const correct
> code to get written. If the rule was changed, the compiler
> would silently compile const-incorrect code causing
> problems in the future.

Sorry, I don't get that at all. How can binding a temporary to a
non-const ref possibly break const correctness? Temporaries aren't
necessarily constant things, in case you'd missed the last 90 or so
posts discussing that. :-)

I've seen several reasonable uses for the proposed change on this
thread. On the other hand, I'm still waiting to see an example in
favour of the status quo that

(a) is clearly a problem, but

(b) wouldn't be fixed by the other changes mentioned on this thread,
notably, giving literal constants the correct type, and forbidding the
binding of non-const refs to *implicitly created* temporaries.

(Having expressed my opinion at the start of this post, I'm not going
to debate the "merits" of using the existing rule to disambiguate
overload resolution any further.)

Regards,
Chris

Gabriel Dos Reis

unread,
Aug 22, 2001, 5:05:31 PM8/22/01
to
neverr...@yahoo.co.uk (Chris Newton) writes:

| Gabriel Dos Reis wrote...
| > "Chris Newton" <chris...@no.junk.please.btinternet.com> writes:
| >
| > [...]
| >
| > | This rule is so obviously contrary to the normal philosophy
| > | of the language that I find it incredible that the standards
| > | committee are here defending it.
| >
| > In this thread you have, at several times, stated things
| > about the "philosophy of C++". Would you pretend to
| > understand better than the creator of C++, what "the philosophy
| > of C++" is?
|
| I would never presume to speak for anyone else,

I never said that you spoke for anyone else (apart for yourself).
However, when you argue along the lines "This rule is so obviously
contrary to the normal philosophy of the language" you implicitly make
the assumption to know what "the philosophy of the language" is.
(FWIW, I personnally don't know what that normal philosophy is)
Furthermore, since you are in disagreement with what was in the ARM,
then your argument makes it that you understand the "philosophy of the
language" better than the creator of the language does/did. In that
respect, my question was exactly that: A question. Do you have the
answer?

[...]

| One of those choices lets the individual programmer do what is correct
| under his or her particular circumstances. The other forces someone
| else's idea of "correct" upon them, on the pretence of increasing
| safety. I feel, as do some others here, that the wrong decision was
| made.

That is your feeling, and I respect it. However, we ought to agree
to disagree.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

Dave Harris

unread,
Aug 23, 2001, 5:23:31 AM8/23/01
to
dos...@cmla.ens-cachan.fr (Gabriel Dos Reis) wrote (abridged):
> Furthermore, since you are in disagreement with what was in the ARM,
> then your argument makes it that you understand the "philosophy of the
> language" better than the creator of the language does/did.

I don't think that follows. Namespaces weren't in the ARM, but I wouldn't
say they were contrary to the philosophy of the language.

Anyway, there's a good take on the "philosophy of C++" in Stroustrup's D&E
chapter 4. Eg the principles:

Don't try to force people.
It is more important to allow a useful feature than to prevent
every misuse.
Leave no room for a lower level language below C++.

My selection is biased, of course :-) However, it seems to me that the
proposed rule (which disallows binding to implicitly created temporaries)
is in accord with almost all of them. The only exception is:

Don't get involved in a sterile question for perfection.

We can always hack the problems with const_cast<> and mutable. Still, I
think we've put forward several strong arguments in favour of the new
rule, and I don't think I've seen any arguments against it (other than
inertia). There *will* be a new C++ standard one day. Personally there are
only 3 language changes I consider important, and this is one of them.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Tom

unread,
Aug 23, 2001, 5:44:47 AM8/23/01
to
On 22 Aug 2001 17:00:40 -0400, neverr...@yahoo.co.uk (Chris
Newton) wrote:

>It's not just broken interfaces; that was simply the first example of
>a constructive use for the feature that I came up with, since it's
>where this thread started. Others have cited further problems with the
>status quo elsewhere.

I've read most of the articles, and I don't recall any particularly
compelling examples.

>> And finally, the non-binding of temporaries to non-const
>> references is one of the things that causes const correct
>> code to get written. If the rule was changed, the compiler
>> would silently compile const-incorrect code causing
>> problems in the future.
>
>Sorry, I don't get that at all. How can binding a temporary to a
>non-const ref possibly break const correctness? Temporaries aren't
>necessarily constant things, in case you'd missed the last 90 or so
>posts discussing that. :-)

I was referring to past examples of code I wrote (when I was starting,
of course :) with function parameters where I left off the const bit
of the references, and then the compiler caught the fact since I tried
to pass a temporary (which required an implicit conversion). I added
the const and all was well (since the ref should have been const).
With the new rule, I would have missed many instances of const
incorrectness in my code. However...

>
>I've seen several reasonable uses for the proposed change on this
>thread. On the other hand, I'm still waiting to see an example in
>favour of the status quo that
>
>(a) is clearly a problem, but
>
>(b) wouldn't be fixed by the other changes mentioned on this thread,
>notably, giving literal constants the correct type, and forbidding the
>binding of non-const refs to *implicitly created* temporaries.

I think the change allowing binding if no implicit conversions is a
reasonable idea - I'd have to give it more thought, and read the rest
of the messages in the thread. It does deal with most of my concerns,
including the minor (but previously unmentioned) situation of most
cases of the const correct code mistake I mention above. Providing
someone can come up with reasonable overloading behaviour. I suspect
that any reasonable behaviour would indeed silently break some
existing code, though I doubt this would be common.

Incidently, I thought that not breaking existing code was a prime
concern of any standard update. Does C99 break much code?

Tom

Markus Schaaf

unread,
Aug 23, 2001, 9:06:08 AM8/23/01
to
"Tom" <tom_u...@hotmail.com> wrote:

> Firstly Gabriel Dos Reis has posted an example of current code that
> would silently change meaning if the new binding was allowed.

Were did he do so? I've browsed the whole thread again and
again, but couldn't find that kind of code. (Just repeating
a statement many times doesn't make it true.)

> This is because of overload resolution.

We never talked about changing overload resolution. If you
are refering to this example:

#include <iostream>

struct X {

void f() { std::cout << "non-const\n"; }
void f() const { std::cout << "const\n"; }
};

void forward_f(X& x)
{ x.f(); }

void forward_f(const X& x)
{ x.f(); }

int main()
{
X x;
forward_f(x);
forward_f(X());
}

This is perfectly valid code. It doesn't make sense to change
its meaning.

To make it clear, what's really intended is adding a kind of
conversion from r-value to l-value, the rank of which would be
worse than any other conversion. This kind of conversion must
not be part of any conversion sequence, but is a "sequence" of
its own (except for an additional identity conversion, which
allows the reference binding).

void swap( T&, T& );
T operator + ( T const&, T const& );

void foo( T& a, T& b )
{
swap( a, a + b );
swap( b, T() );
}

(I'm sure one wouldn't write anything like that by mistake.)

> Secondly, many compilers allow the binding as an extension (warnings
> are usually issued, and I don't know how overload resolution is dealt
> with). If, like Chris Newton, you are working with a broken interface
> that you can't fix, then perhaps you should use the extension.

You are joking? Such extensions are useless if you do
programming for any other purpose than wasting time. And as
somebody noted, some of these do break code.

Yours sincerely

Gabriel Dos Reis

unread,
Aug 23, 2001, 5:52:12 PM8/23/01
to
"Markus Schaaf" <m.schaaf.e...@gmx.de> writes:

| "Tom" <tom_u...@hotmail.com> wrote:
|
| > Firstly Gabriel Dos Reis has posted an example of current code that
| > would silently change meaning if the new binding was allowed.
|
| Were did he do so?

In the example youu quoted.

[...]

| > This is because of overload resolution.
|
| We never talked about changing overload resolution. If you
| are refering to this example:
|
| #include <iostream>
|
| struct X {
|
| void f() { std::cout << "non-const\n"; }
| void f() const { std::cout << "const\n"; }
| };
|
| void forward_f(X& x)
| { x.f(); }
|
| void forward_f(const X& x)
| { x.f(); }
|
| int main()
| {
| X x;
| forward_f(x);
| forward_f(X());
| }
|
| This is perfectly valid code. It doesn't make sense to change
| its meaning.

So, if temporaries are allowed to be bound to non-const reference,
what should be the semantics of the above program?

| To make it clear, what's really intended is adding a kind of
| conversion from r-value to l-value, the rank of which would be
| worse than any other conversion.

A preceise formulation would be very helpful for continuing a sound
discussion? Do you have a first take?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Aug 23, 2001, 5:52:30 PM8/23/01
to
bran...@cix.co.uk (Dave Harris) writes:

| dos...@cmla.ens-cachan.fr (Gabriel Dos Reis) wrote (abridged):
| > Furthermore, since you are in disagreement with what was in the ARM,
| > then your argument makes it that you understand the "philosophy of the
| > language" better than the creator of the language does/did.
|
| I don't think that follows. Namespaces weren't in the ARM,

We were speaking -specically- of *binding temporaries to non-const
reference*. Did you miss that?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

It is loading more messages.
0 new messages