Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Assignment operator=/copy constructor/temporaries, BROKEN!

Reply
Thread Tools

Assignment operator=/copy constructor/temporaries, BROKEN!

 
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      09-19-2010
* Fabrizio J Bonsignore, on 19.09.2010 04:36:
> On Sep 18, 2:39 am, Kai-Uwe Bux<(E-Mail Removed)> wrote:
>> Fabrizio J Bonsignore wrote:
>>> The other error is similar:

>>
>>> [line] no matching function for call to `AO::AO(AO)'
>>> [line] candidates are: AO::AO(AO&)
>>> [line] AO::AO()

>>
>>> !!! Which is nonsense!

>>
>> The const is not and was not optional: clause [8.5.3/5] has been in the
>> standard from the start (199.
>>

>
> It IS optional even if included in the _description_ of the language.
> But I ve been programming C++ since 1992! It was already a well
> established language and superior to C, Pascal, Basic, macro
> languages...


In 1992 the effective language definition (not yet standardized) was "The
Annotated Reference Manual", popularly called the ARM, by Margaret Ellis and
Bjarne Stroustrup; my copy was published in 1990.

The ARM defined a copy constructor similarly to how the standard does today,
namely that a copy constructor for a class X "can be called with a single
argument of type X". Furthermore, the first formal argument can't be
pass-by-value. Hence, the first formal argument must be passed by reference.

This does not require the formal argument to be 'const', but if the formal
argument isn't 'const' then you can't pass an rvalue as actual argument, since
an rvalue can't be bound to a reference to non-const.

The ARM specified that only an lvalue can be bound to a reference to non-const,
in section §8.4.3.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      09-19-2010
On 09/19/10 02:25 PM, Fabrizio J Bonsignore wrote:
> On Sep 18, 7:28 am, James Kanze<(E-Mail Removed)> wrote:
>> On Sep 17, 8:57 pm, Fabrizio J Bonsignore<(E-Mail Removed)> wrote:
>>
>> The const in these is *not* optional, and hasn't been since
>> CFront 2.1 (1989, or some time around then). You cannot
>> initialize a non-const reference with a temporary (and the
>> results of a function call is a temporary).
>>
>> Some compilers have been a bit slow about enforcing this, but
>> that's not a general rule; it was enforced by compilers I was
>> using in the early 1990's.

>
> I have another project open, the compiler accepts a copy constructor
> and finds it without const and without errors, compile time or run
> time. This problem was surprising!


Not really. As Alf pointed out, the copy constructor can use a const or
a non-const reference parameter.

>> Different errors are detected at different phases of
>> compilation. A constructor AO::AO(AO) is illegal---it would be
>> useless if it weren't, since it would result in infinite
>> recursion if it were ever called.

>
>
> That seems to be a REAL bug in the compiler: the problem is something
> different, it should mention the lack of const as a warning (AT MOST,
> I insist current practice is to make const optional), and the form of
> such error message is so easily detectable that it can be substituted
> by anything else in the next error reporting pass, if not completely
> changed.


Pass by value to a copy constructor, whether const or not is not
permitted by the language rules. What happens when an object is passed
by value? It gets copied!

--
Ian Collins
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      09-19-2010
Fabrizio J Bonsignore wrote:

> On Sep 18, 2:39 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
>> Fabrizio J Bonsignore wrote:
>> > The other error is similar:

>>
>> > [line] no matching function for call to `AO::AO(AO)'
>> > [line] candidates are: AO::AO(AO&)
>> > [line] AO::AO()

>>
>> > !!! Which is nonsense!

>>
>> The const is not and was not optional: clause [8.5.3/5] has been in the
>> standard from the start (199.
>>

>
> It IS optional even if included in the _description_ of the language.


You snipped context, where I explained that [8.5.3/5] implies that your
code _will_ compile and work with "const" but won't without. So, in that
precise sense "const" is _not_optional_ in the code snippet you presented.

Also, I did not choose that meaning of "optional"; you did when you wrote:

> It SEEMS to work with AO:: (const AO &) in BOTH copy constructor and
> assignment operators, the compiler accepts it (compile time), but
> const here is almost optional and has been so since ever.


Note the operative word "here", which I took to mean that you are refering
const in the very code snippet under discussion.

> But I ve been programming C++ since 1992! It was already a well
> established language and superior to C, Pascal, Basic, macro
> languages... Adding const was a nuisance then and besides the way C++
> is layered, and given access specifiers, well programmed classes will
> never have side effect troubles from non sprinkling const liberally! I
> insist such is the case that the const_cast<> operator had to be
> added.


You are, of course, entitled to your opinion about const. However, note that
you problem does not stem from the introduction of the "const" keyword. It
is a consequence of non-const references not binding to temporaries; and I
have issues with that provision. E.g., I think the following does't make all
that much sense:

typedef std::vector< int > int_vector;
int_vector the_vector;

std::swap( the_vector, int_vector() ); // illegal
the_vector.swap( int_vector() ); // illegal
int_vector().swap( the_vector ); // OK

> In any case, standards are complex documents and their link to
> actual working and functioning practice is similar to the relationship
> between Life and Movies or Literature... Too late... but maybe it
> would be worth the while to first describe WORKING languages as they
> ARE, then comparatively design a future fantasy, because it seems that
> industry standard practice is stronger than **standard documents**.


Apparently, the compilers you are using are rejecting the code without
const. I can only conclude that the standard is actually strong enough to
shape industry practice. (At least in this regard, it did not bring "export"
to the masses, though.)


Best

Kai-Uwe Bux

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      09-19-2010
On Sep 19, 3:25 am, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:
> On Sep 18, 7:28 am, James Kanze <(E-Mail Removed)> wrote:


> > On Sep 17, 8:57 pm, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:


> > The const in these is *not* optional, and hasn't been since
> > CFront 2.1 (1989, or some time around then). You cannot
> > initialize a non-const reference with a temporary (and the
> > results of a function call is a temporary).


> > Some compilers have been a bit slow about enforcing this,
> > but that's not a general rule; it was enforced by compilers
> > I was using in the early 1990's.


> I have another project open, the compiler accepts a copy
> constructor and finds it without const and without errors,
> compile time or run time.


There's no problem defining a copy constructor without const.
You just can't use it to copy rvalues (like the return value of
a function).

> > > Compared to the use of const, the solution AO::AO(AO *a);
> > > AO a(&Function()); (take address of some temporary), seems
> > > preferable,


> Oh, but it DID accept it!


That must be VC++. I recently encountered the same thing:
someone had taken the address of a temporary, and it compiled
under VC++. But failed to compile with g++ (under Linux).

Regardless of what VC++ says, it's not legal C++.

[...]
> AO a( &(object.method(argument)).functionReturningAO( ) );


> and it passes compilation. Should I leave it like that?


Only if you're not writing C++, and are sure you'll never have
to compile it with anything other than the compiler you're
currently using. (I wonder if VC++ 10 accepts it. Microsoft is
moving gradually to a policy of respecting the standard.)

--
James Kanze
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      09-19-2010
On 19 sept, 05:25, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:
> On Sep 18, 7:28*am, James Kanze <(E-Mail Removed)> wrote:
>
> > On Sep 17, 8:57 pm, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:

>
> > The const in these is *not* optional, and hasn't been since
> > CFront 2.1 (1989, or some time around then). *You cannot
> > initialize a non-const reference with a temporary (and the
> > results of a function call is a temporary).

>
> > Some compilers have been a bit slow about enforcing this, but
> > that's not a general rule; it was enforced by compilers I was
> > using in the early 1990's.

>
> I have another project open, the compiler accepts a copy constructor
> and finds it without const and without errors, compile time or run
> time. This problem was surprising! That other class does derive from a
> Windows struct and has conversion semantics to it, it defines both
> assignment operator= and copy constructor without const... and the
> compiler accepts it. I ll have to review that code to see which one of
> my cases (in a previous post) I did NOT use in that project that the
> compiler did not fail. I am quite liberal in the use of that beefed up
> struct as it is now a very basic variable/object in that system and
> there has been no such weird error messages. But this may be the case
> because it actually IS-A Windows defined struct, so the actual Windows
> definition may be affecting compilation. OF COURSE this means to me
> more testing...


You probably misunderstood what James did say.

No testing is needed ...
12.8/2: "A non-template constructor for class X is a copy constructor
if its first parameter is of type X&, const X&, volatile X&
or const volatile X&, and either there are no other parameters
or else all other parameters have default arguments (8.3.6)."

Therefore the non-const version is a copy constructor as well. Only
thing is that it can not take temporary as argument. Visual C++ let to
use temporary argument there as "extension". I had to explain to
novice coworkers that exploiting such an "extension" is out of
question and warning about it (at least VS 2005 warns) must be treated
as error.
 
Reply With Quote
 
Goran
Guest
Posts: n/a
 
      09-19-2010
On Sep 19, 4:36*am, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:
> But I ve been programming C++ since 1992! It was already a well
> established language and superior to C, Pascal, Basic, macro
> languages... Adding const was a nuisance


What a strange thing to say! "const" has been in C++ since forever; it
was picked up from C, a predecessor of C++. "const" exists in other
languages, albeit perhaps not in same form or functionality (arguably
D language does it better, but C heritage of C++ is a PITA).

And it's not a nuisance, but a tool. Some even say that this
particular tool helps them write better code.

Goran.
 
Reply With Quote
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-19-2010
On Sep 18, 11:29*pm, Ian Collins <(E-Mail Removed)> wrote:
> On 09/19/10 02:25 PM, Fabrizio J Bonsignore wrote:
>
> Not really. *As Alf pointed out, the copy constructor can use a const or
> a non-const reference parameter.


Then that was the ARM and if this reference is exact, const was
ancillary, the point is "called with a single argument of type X"

> Pass by value to a copy constructor, whether const or not is not
> permitted by the language rules. *What happens when an object is passed
> by value? *It gets copied!


Indeed! An infinite recursion by necessity or you use bitwise copy at
some point, so why a copy constructor then? But see that strictly
speaking, the statement:

AO x = Function();

should call: the default constructor to build AO x; some copy
constructor to take the AO out of Function() to be used as argument...
to a call to the assignment operator between default constructed x and
the returned COPY of AO from AO Function();!!! Basically we want such
statement to be optimized! But it is supposedly equivalent to:

AO x(Function());

See that const is irrelevant, what matters is that here we need: a
copy constructor to bring the AO object out of Function() AND the
invocation of the copy constructor to place data into x. This seems to
be the case the compiler is confusing so it keeps asking for
AO::AO(AO) and cant see AO::AO(AO &) [no const]: the AO::AO(AO) it
cannot find is... the **copy constructor** before the actual copy
constructor for x; ! Then it seems adding const only helps it select a
case to avoid a spureous call the out-of-function copy constructor.
But ultimately in a REAL sense, the temporary does have a name: its
name is literally speaking

AO AO_BO_Function_void;

underscores more or less, and that is the name we want bound to the
final name _s_ in AO::AO(AO s) {...} or AO::AO(AO &s) {...} or even
AO::AO(const AO &s) {...}

My issue is still that this compiler is inconsistent in what it
accepts. But then I want a statement like AO x = Function(); to MEAN
**the new name of AO_BO_Function_void IS x and &x =
&AO_BO_Function_void**. If the compiler does MOVE the address of
AO_BO_Function_void between its creation and the final binding to name
x, is irrelevant too and system defined as long as this __assignment__
is done efficiently. So, should it call an intermediate function,
assignment operator= or copy constructor in this case? Or is it acting
logically and calling all THREE methods for each statement of the
like?

Note that

AO x;
//some work with x
x = Function();
//some work with new x contents

is expected to call the assignment operator= unambiguously, and the
copy constructor should be just a convenience (bitwise compiler
generated copy OR name binding). x is just a convenience variable
name. But for this statements also the compiler is complaining
accepting both const and non const versions depending on whether const
is used once, once or twice or none at all.

Also note that Function() becomes an expression, not a statement, in
the assignation of value, so something more complex like:

AO x = ((flag)?Retut():Retit());

makes more difficult for the compiler to get the REAL name of the
temporary (also the real name cannot be correctly bound easily in the
definition of Function() unless the compiler determines which of many
possible objects will become the final returned value, though the
compiler must make provisions to assign memory for the final returning
**value** AND garbage it after use). But if that is the problem then
const or pass by reference are just obviating it and the real problem
is to associate some syntax to some optional wrapping code, which was
supposedly a non problem but suddenly is A problem for this compiler!

Danilo J Bonsignore
 
Reply With Quote
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-19-2010
WOW!

On Sep 19, 5:45*am, James Kanze <(E-Mail Removed)> wrote:
> On Sep 19, 3:25 am, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:
>
> That must be VC++. *I recently encountered the same thing:
> someone had taken the address of a temporary, and it compiled
> under VC++. *But failed to compile with g++ (under Linux).
>


It _IS_ compiling in g++ and I cannot test in VC+. The code in
question is the above in this thread, the one defining BO objects as
callers. In the real source the object begun its life as an inner
class talking to another inner class in a singleton static object and
I have no doubt it would compile in VC+, but I had to break the scheme
in g++ just to find out there IS an error message.
 
Reply With Quote
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-19-2010
On Sep 19, 6:22*am, Öö Tiib <(E-Mail Removed)> wrote:
> 12.8/2: "A non-template constructor for class X is a copy constructor
> * * * * if its first parameter is of type X&, const X&, volatile X&
> * * * * or const volatile X&, and either there are no other parameters
> * * * * or else all other parameters have default arguments (8.3.6)."
>


INDEED! const is optional. g++ 3.4.2 has a bug and it points to a
incomprehension about the language issue or languages in general by
the implementors. Basically, you should be very well versed and
experienced in languages development if you implement a general use
language for the public and it is what all people would expect, not
some personally interesting experimentation to acquire expertise. The
closest reference to the same problem I found is

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44158

A **move** constructor AO::AO(AO &&) seems interesting but is no
solution to a bad implementation of the most basic language defining
feature though!

Danilo J Bonsignore
 
Reply With Quote
 
LR
Guest
Posts: n/a
 
      09-19-2010
Fabrizio J Bonsignore wrote:
> WOW!
>
> On Sep 19, 5:45 am, James Kanze <(E-Mail Removed)> wrote:
>> On Sep 19, 3:25 am, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:
>>
>> That must be VC++. I recently encountered the same thing:
>> someone had taken the address of a temporary, and it compiled
>> under VC++. But failed to compile with g++ (under Linux).
>>

>
> It _IS_ compiling in g++ and I cannot test in VC+. The code in
> question is the above in this thread, the one defining BO objects as
> callers. In the real source the object begun its life as an inner
> class talking to another inner class in a singleton static object and
> I have no doubt it would compile in VC+, but I had to break the scheme
> in g++ just to find out there IS an error message.


Sorry I missed the temporary value and non-const reference.

Do you have access to lint?

Looking at the lint errors for the sample code you posted leads me to
some conclusions about the error messages you posted else thread, your
second example was:

[line] no matching function for call to `AO::AO(AO)'
[line] candidates are: AO::AO(AO&)
[line] AO::AO()

Which I think came from a line in your example like:
AO o(Retit());

Which you said was nonsense. After some consideration, I don't think it is.

I think the compiler is trying to tell you that you're trying to
construct something from a temporary here, and then which ctors it tried
to use to match the call.

Can you try adding a line to your code like,
AO o("Hello");
and seeing if you get error messages that with comparison to the above
messages makes the errors easier to understand?


LR

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Assignment operator self-assignment check Chris C++ 34 09-26-2006 04:26 AM
Augument assignment versus regular assignment nagy Python 36 07-20-2006 07:24 PM
Question about interference and Wireless Channel Assignment HOESan Wireless Networking 4 09-04-2004 08:36 PM
Comparison of Bit Vectors in a Conditional Signal Assignment Statement Anand P Paralkar VHDL 2 08-04-2003 08:40 PM
Help: conditional attribute assignment itsme VHDL 1 07-23-2003 03:26 PM



Advertisments