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!

 
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-17-2010
On Sep 17, 3:12*pm, Öö Tiib <(E-Mail Removed)> wrote:
> If you did not declare copy constructor and assignment operator then
> compiler produces these for you (expect for cases the class was made
> not copyable). That has been so as long i remember in C++ so i do not
> get what you complain there.


Indeed, it works automatically and will generate errors if you are
using pointers and managing your own memory. The AO has also been
normal C++ as long as I remember but now it is not working well. The
error message says:

[line] no match for 'operator=' in 'f = BO::Retit()()'
[line] candidates are AO& operator=(AO&);

!!! Precisely!

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!

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. Strictly
speaking it is not the same as AO::AO(AO const &x)... and you would
even have to disambiguate to the extreme of AO::AO(const AO const &
const a)... and add all variants for BOTH assignment and copy
constructors! In the program this problem arose it is NOT the case: I
need a SINGLETON, actually I need some UNIQUE reading to propagate
after initial construction wherever objects of primitive class AO take
it, UNTIL any of them is Closed(); which means in one scenario (maybe
at most) I have to discard the reading from the copied object...
violating the const. It is NOT FUNNY that the suggestion was
AO::AO(const AO &) and not AO::AO(AO const &) or AO::AO(AO & const);
the latter variants did not compile! This code here is trivial and
does nothing, but in real code I cannot truly know if I can honor ANY
constness in the argument object! Which means the risk of needing to
defining different signatures with almost identical code to handle all
possibilities! Compared to the use of const, the solution AO::AO(AO
*a); AO a(&Function()); (take address of some temporary), seems
preferable, but the problem is still the insistence of g++ 3.4.2 in
finding AO::AO(AO) (!) when later it would say it IS an illegal copy
constructor signature.

Danilo J Bonsignore
 
Reply With Quote
 
 
 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      09-17-2010
Fabrizio J Bonsignore wrote:

> What is the point of OOP and C++, anyway? I want to write ... AO
> Function(); ... AO x = Function(); I want some NEW x object of type AO
> in its relevant scope to CATCH the AO object returned from function
> Function(); copy it and become IT. I do NOT want to have a previous AO
> object initialized in default values, AO x; THEN an assignment
> operator called on it with Function(); [like in x.this-


Don't feed the troll...
 
Reply With Quote
 
 
 
 
LR
Guest
Posts: n/a
 
      09-17-2010
Fabrizio J Bonsignore wrote:
> On Sep 17, 3:12 pm, Öö Tiib <(E-Mail Removed)> wrote:
>> If you did not declare copy constructor and assignment operator then
>> compiler produces these for you (expect for cases the class was made
>> not copyable). That has been so as long i remember in C++ so i do not
>> get what you complain there.

>
> Indeed, it works automatically and will generate errors if you are
> using pointers and managing your own memory.


I thought the default copy ctor in this case would generate a shallow
copy of the argument.

> The AO has also been
> normal C++ as long as I remember but now it is not working well. The
> error message says:
>
> [line] no match for 'operator=' in 'f = BO::Retit()()'
> [line] candidates are AO& operator=(AO&);
>
> !!! Precisely!


What happens if you change that to

AO &operator=(const AO &);


>
> 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!


These look like they may be compiler bugs, or else you may be compiling
something different than what you posted.


>
> 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. Strictly
> speaking it is not the same as AO::AO(AO const &x)...


That seems pretty strict. I'm not sure how

A0::AO(const AO &)
and
AO::AO(const AO &x)

are different for purposes of this discussion. Can you please explain that?


> and you would
> even have to disambiguate to the extreme of AO::AO(const AO const &
> const a)... and add all variants for BOTH assignment and copy
> constructors!


I'm not sure I follow that. I thought that

AO(const AO &); and AO(AO const &); were equivalent. The compiler I use
thinks so too. http://www.comeaucomputing.com/tryitout/ seems to
indicate that this is the case as well.

> In the program this problem arose it is NOT the case: I
> need a SINGLETON, actually I need some UNIQUE reading to propagate
> after initial construction wherever objects of primitive class AO take
> it, UNTIL any of them is Closed(); which means in one scenario (maybe
> at most) I have to discard the reading from the copied object...
> violating the const.


I'm not sure that I follow all of that, but it sounds like you want to
be able to partially construct and object and perhaps not complete
construction depending on some resource. Is that right?



> It is NOT FUNNY that the suggestion was
> AO::AO(const AO &) and not AO::AO(AO const &) or AO::AO(AO & const);
> the latter variants did not compile!


If you try them all together at once I don't think they will compile.
And this Q(Q & const) {} got me a warning about an anachronism from my
compiler.

> This code here is trivial and
> does nothing, but in real code I cannot truly know if I can honor ANY
> constness in the argument object!


But I'm confused as to why. When you call a ctor with a const
reference, that object is, was, already constructed and it's not clear
to me that you want to alter the already constructed argument. Or
perhaps a slightly different design is what's needed since I think that
a copy ctor that alters the argument tends, not always, but tends, to
violate the principle of least astonishment. IMO.

Or do you want to call a ctor with an argument that is only partially
constructed? I don't think that's really possible. I think it's very
likely that I don't understand what you mean. Maybe a small real world
example is called for?

> Which means the risk of needing to
> defining different signatures with almost identical code to handle all
> possibilities! Compared to the use of const, the solution AO::AO(AO
> *a); AO a(&Function()); (take address of some temporary), seems
> preferable, but the problem is still the insistence of g++ 3.4.2 in
> finding AO::AO(AO) (!) when later it would say it IS an illegal copy
> constructor signature.



Again, this seems very peculiar. Also, from reading here
http://gcc.gnu.org/ it seems that gcc 4.5.1 has been released.

I think you've implied that gcc 3.4.2 is not the compiler that you've
been using with this code. Is using this compiler a recent change?

Do you get these errors when you compile the code that you posted here?

LR


 
Reply With Quote
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-17-2010
Oops!

On Sep 17, 5:38*pm, LR <(E-Mail Removed)> wrote:
> Fabrizio J Bonsignore wrote:
> > On Sep 17, 3:12 pm, Öö Tiib <(E-Mail Removed)> wrote:
> >> If you did not declare copy constructor and assignment operator then
> >> compiler produces these for you (expect for cases the class was made
> >> not copyable). That has been so as long i remember in C++ so i do not
> >> get what you complain there.

>
> > Indeed, it works automatically and will generate errors if you are
> > using pointers and managing your own memory.

>
> I thought the default copy ctor in this case would generate a shallow
> copy of the argument.


Indeed a shallow bitwise copy of member object data, so if any of them
is a pointer (heap memory), you end up with two copies of the same
pointer value! Which means you cannot simply delete the pointer in the
destructor because you would delete it twice so that particular object
cannot manage that pointer s memory! The common case is char *texts,
each instance has its own text (if necessary), or can choose to make
it 0, which makes sense if the text is user initialized! For example,
you copy a bitmap object (bitwise data), then wait for the user to
give it a name or it ends up recorded as noname [if ((char *)text ==
0...)] Shallow copy constructors are unacceptable here.

> > The AO has also been
> > normal C++ as long as I remember but now it is not working well. The
> > error message says:

>
> > [line] no match for 'operator=' in 'f = BO::Retit()()'
> > [line] candidates are AO& operator=(AO&);

>
> > !!! Precisely!

>
> What happens if you change that to
>
> AO &operator=(const AO &);
>

That s the solution you provided! And it worked as long as BOTH
assignment operator and copy constructor are signed as (const AO &);

>
> > 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!

>
> These look like they may be compiler bugs, or else you may be compiling
> something different than what you posted.
>

It is the case, seems to be a bug in the compiler but it MAY be a
combination of compiler flags that has to be defined to avoid that
error. In any case it is in the compiler where you do NOT expect nor
can accept bugs at all... or your code becomes undefined!

>
> > 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. Strictly
> > speaking it is not the same as AO::AO(AO const &x)...

>
> That seems pretty strict. I'm not sure how
>
> A0::AO(const AO &)
> and
> AO::AO(const AO &x)
>
> are different for purposes of this discussion. Can you please explain that?
>

Should not matter, but you can ask for a warning on the lines of:
unused function argument or something similar. I ve always considered
signature argument names as documentation and definition argument
names as minimum name variables, but since the language can accept
function calls in the SIGNATURE of a member function (even anonymous
classes lately...), I always define them even if unneeded for the
method (like the int in post/pre fix operator++).

> > *and you would
> > even have to disambiguate to the extreme of AO::AO(const AO const &
> > const a)... and add all variants for BOTH assignment and copy
> > constructors!

>
> I'm not sure I follow that. *I thought that
>

You can consider the REFERENCE as const or the OBJECT REFERRED TO as
const or the VARIABLE NAME as const... or all three... but I omit
const as far as possible. In worst cases const propagates to all
methods of a class! So you end up having version void F(AO); void
F(const AO); etc. duplicated, but doing exactly the same, to the
extent the const_cast operator became necessary to take away/add const
in hard cases. I never use it, so I am not sure of all the
consequences and differences between those signatures, though the
difference is real for the compiler, or should be.

> AO(const AO &); and AO(AO const &); were equivalent. The compiler I use
> thinks so too.http://www.comeaucomputing.com/tryitout/seems to
> indicate that this is the case as well.
>

Nope, it may be but you can read both version as different
referents... const AO says that the object cannot stop being an AO! If
that is the case (more testing...), how can you pass it as argument to
a BASE CLASS copy constructor? Strictly speaking you would have to
cast down to base class and even take away the const first, cast, then
add the const again! But too much expliciting of polymorphism actually
DESTROYS IT, you want your polymorphism to be TRANSPARENT for the user
because it hides complexity.

> > In the program this problem arose it is NOT the case: I
> > need a SINGLETON, actually I need some UNIQUE reading to propagate
> > after initial construction wherever objects of primitive class AO take
> > it, UNTIL any of them is Closed(); which means in one scenario (maybe
> > at most) I have to discard the reading from the copied object...
> > violating the const.

>
> I'm not sure that I follow all of that, but it sounds like you want to
> be able to partially construct and object and perhaps not complete
> construction depending on some resource. Is that right?


Specifically I wanted to erase the reading from the copied object and
_move_it_ into the new, copied-to object, so the original object would
not invoke Close() in the destructor after finding an empty reading.
This assumes new objects s lifespans are longer than the sources and
get destructed later, which is a very good assumption IF you copy
around objects by value! The original gets destroyed in the
originating function, the function that catches it now has the rading
and MAY be the function that ultimately can call Close() or destroy
the object to get a final legitimate reading.

> > It is NOT FUNNY that the suggestion was
> > AO::AO(const AO &) and not AO::AO(AO const &) or AO::AO(AO & const);
> > the latter variants did not compile!

>
> If you try them all together at once I don't think they will compile.
> And this Q(Q & const) {} got me a warning about an anachronism from my
> compiler.


}-) That s the point! It takes time to test... but here the point is
other similar posts all suggest (AO const &) [const reference to
object of type AO] and not the _working_ const object of type AO taken
by reference. I am not sure, but that anachronism may mean you can
only call some methods on the [ommitted] variable and not others
depending on the placement of their constness const int F(); vs int
F() const; Which IS one the reason why I am perplexed that the
compiler does not let me decide if I change the argument object in a
constructor or not.

> > This code here is trivial and
> > does nothing, but in real code I cannot truly know if I can honor ANY
> > constness in the argument object!

>
> But I'm confused as to why. *When you call a ctor with a const
> reference, that object is, was, already constructed and it's not clear
> to me that you want to alter the already constructed argument. *Or
> perhaps a slightly different design is what's needed since I think that
> a copy ctor that alters the argument tends, not always, but tends, to
> violate the principle of least astonishment. IMO.
>

I am astonished. Reference counting seems to be the typical case where
constness can be broken by necessity, but there are other schemes.
const means that you agree NOT to modify the argument, which is why
you have to define const methods if you want to call methods at all!
It makes for very inefficient programming... The bad C assumption is
that all you can and want to do with the argument is to copy data, but
it IS the natural place to perform initializations, management,
profiling, synchronizations... because the argument is an OBJECT and
includes methods. O CloneX() seems to be a valid method to define and
call in a copy constructor method for members of type O.

> Or do you want to call a ctor with an argument that is only partially
> constructed? *I don't think that's really possible. I think it's very
> likely that I don't understand what you mean. Maybe a small real world
> example is called for?


But that seems to be what the compiler is doing! It SEEMS to be
creating a temporary with the default constructor, then complaining
that it cannot assign it (because it is partially constructed)! The
error Retut()() implies (Retut()=AO)() === default constructor, then
gets lost because it cannot call in addition AO(AO...)!

> > Which means the risk of needing to
> > defining different signatures with almost identical code to handle all
> > possibilities! Compared to the use of const, the solution AO::AO(AO
> > *a); AO a(&Function()); (take address of some temporary), seems
> > preferable, but the problem is still the insistence of g++ 3.4.2 in
> > finding AO::AO(AO) (!) when later it would say it IS an illegal copy
> > constructor signature.

>
> Again, this seems very peculiar. Also, from reading herehttp://gcc.gnu.org/it seems that gcc 4.5.1 has been released.
>
> I think you've implied that gcc 3.4.2 is not the compiler that you've
> been using with this code. Is using this compiler a recent change?
>
> Do you get these errors when you compile the code that you posted here?
>

.... gcc 4.5.1 seems to keep adding and adding to the language... and
to the list of BUGS. 4.5.1 means to go through a new installation but
I got my version bundled. I was reading the known bugs and it seems to
keep changing things to new features I do not plan to use which
besides are still buggy! My point is that the code I posted here [AO
and BO] is such typical and basic C++ it has to compile. The version I
ve been using exclusively is 3.4.2 I do not want to change it...
unless it has a real crucial error. Which is what I want to determine.

Danilo J Bonsignore
 
Reply With Quote
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-17-2010
On Sep 16, 10:04*pm, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:
> Like in AO::AO((AO &)(AO&)Function()); so both (AO &) terms cancel each other out AS IF this was a mathematical algebra...


This seems to be an undocumented or misclassified bug in the compiler
frontend. It seems to be comparing directly and literally the
signature of the copy constructor, taking a reference, and the
signature of any function returning the same object type by value.
Since the function does not return a reference... the constructor does
not take the value by reference! The SEMANTIC is DIFFERENT, but in the
code the comparison seems to be SYNTACTIC and literal! Strictly
speaking should be a less or greater equal than comparison, not an
equal to comparison. The programmer is taking the return type of a
function, then matching literally against the known signatures for
constructors in the class (at least forward defined as the function is
in another object). Since literally the AO in AO Function(); is NOT
identical to AO& in the constructor... it asks for an illegal
AO::AO(AO) constructor! But if the function is defined as AO&
Function(); THEN the literal identical match succeeds! The programmer
would have to make something like if (AO == AO || AO == AO&) accept();
In actual code the situation may be hidden by the temporary. The error
message no match ... ::Retut()() implies a temporary spureous call to
the default constructor!

Of course I have no indication this problem is not carried into next
versions unless the bug is documented, but I still have doubts if it
is a spureous bug that will go away by writing more code or a hidden
bug that will explode at the least expected moment (say, in some
multithreading or window switching contexts)! So far it shows up in
this project but not in another project. The other project does not
exhaust copying possibilities while here I am using all possibilities.
It shows up for an empty class too built ex professo but goes away
with both workarounds.

Danilo J Bonsignore
 
Reply With Quote
 
LR
Guest
Posts: n/a
 
      09-18-2010
Fabrizio J Bonsignore wrote:
> Oops!
>
> On Sep 17, 5:38 pm, LR <(E-Mail Removed)> wrote:
>> Fabrizio J Bonsignore wrote:
>>> On Sep 17, 3:12 pm, Öö Tiib <(E-Mail Removed)> wrote:
>>>> If you did not declare copy constructor and assignment operator then
>>>> compiler produces these for you (expect for cases the class was made
>>>> not copyable). That has been so as long i remember in C++ so i do not
>>>> get what you complain there.

>>
>>> Indeed, it works automatically and will generate errors if you are
>>> using pointers and managing your own memory.

>>
>> I thought the default copy ctor in this case would generate a shallow
>> copy of the argument.

>
> Indeed a shallow bitwise copy of member object data, so if any of them
> is a pointer (heap memory), you end up with two copies of the same
> pointer value! Which means you cannot simply delete the pointer in the
> destructor because you would delete it twice so that particular object
> cannot manage that pointer s memory! The common case is char *texts,
> each instance has its own text (if necessary), or can choose to make
> it 0, which makes sense if the text is user initialized! For example,
> you copy a bitmap object (bitwise data), then wait for the user to
> give it a name or it ends up recorded as noname [if ((char *)text ==
> 0...)] Shallow copy constructors are unacceptable here.
>
>>> The AO has also been
>>> normal C++ as long as I remember but now it is not working well. The
>>> error message says:

>>
>>> [line] no match for 'operator=' in 'f = BO::Retit()()'
>>> [line] candidates are AO& operator=(AO&);

>>
>>> !!! Precisely!

>>
>> What happens if you change that to
>>
>> AO &operator=(const AO &);
>>

> That s the solution you provided! And it worked as long as BOTH
> assignment operator and copy constructor are signed as (const AO &);


Maybe that's the fix you're looking for then.

I'm wondering if this is related
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16889

Followed link from http://gcc.gnu.org/gcc-3.4/changes.html#3.4.2
Followed link from http://gcc.gnu.org/gcc-3.4/

>
>>
>>> 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!

>>
>> These look like they may be compiler bugs, or else you may be compiling
>> something different than what you posted.
>>

> It is the case, seems to be a bug in the compiler but it MAY be a
> combination of compiler flags that has to be defined to avoid that
> error. In any case it is in the compiler where you do NOT expect nor
> can accept bugs at all... or your code becomes undefined!


gcc 3.4.2 was released in 2004. Compilers have bugs. You can find the
list for 3.4.2 at one of the links above. Although, this seems like a
fairly fundamental thing.

[snip]

> You can consider the REFERENCE as const or the OBJECT REFERRED TO as
> const or the VARIABLE NAME as const... or all three...


I don't follow that as all.

I think that references are const. You can't change them once they're
initialized. An object that is referenced can be const. The variable
name? You've lost me there. I don't know what that means.

> but I omit
> const as far as possible. In worst cases const propagates to all
> methods of a class! So you end up having version void F(AO); void
> F(const AO); etc. duplicated, but doing exactly the same,


No. They don't do the same thing, and this can be very useful.
Personally I think it's much easier to write and debug code where as
much as possible is const. But maybe that's just me.


>> AO(const AO &); and AO(AO const &); were equivalent. The compiler I use
>> thinks so too.http://www.comeaucomputing.com/tryitout/seems to
>> indicate that this is the case as well.
>>

> Nope, it may be but you can read both version as different
> referents... const AO says that the object cannot stop being an AO! If
> that is the case (more testing...), how can you pass it as argument to
> a BASE CLASS copy constructor?


I'm not sure I understand. Do you mean like this:

class Base {
....
public:
Base(const Base &b) {}
};

class Derived : public Base {
.....
public:
Derived(const Derived &d) : Base(d) {}
};

I don't see the problem.


> Strictly speaking you would have to
> cast down to base class and even take away the const first, cast, then
> add the const again! But too much expliciting of polymorphism actually
> DESTROYS IT, you want your polymorphism to be TRANSPARENT for the user
> because it hides complexity.


I'm sorry, but I still don't see the problem.

[snip]

> Specifically I wanted to erase the reading


I'm not sure what you mean by "erase the reading".

> from the copied object and
> _move_it_ into the new, copied-to object, so the original object would
> not invoke Close() in the destructor after finding an empty reading.



An empty reading? Are you reading a file to construct your object?

> This assumes new objects s lifespans are longer than the sources and
> get destructed later, which is a very good assumption IF you copy
> around objects by value! The original gets destroyed in the
> originating function, the function that catches it


Are you throwing an exception?


> now has the rading
> and MAY be the function that ultimately can call Close() or destroy
> the object to get a final legitimate reading.


Sorry. I don't understand that.

>
>>> It is NOT FUNNY that the suggestion was
>>> AO::AO(const AO &) and not AO::AO(AO const &) or AO::AO(AO & const);
>>> the latter variants did not compile!

>>
>> If you try them all together at once I don't think they will compile.
>> And this Q(Q & const) {} got me a warning about an anachronism from my
>> compiler.

>
> }-) That s the point! It takes time to test... but here the point is
> other similar posts all suggest (AO const &) [const reference to
> object of type AO] and not the _working_ const object of type AO taken
> by reference. I am not sure, but that anachronism may mean you can
> only call some methods on the [ommitted] variable and not others
> depending on the placement of their constness const int F(); vs int
> F() const;


Assuming that both of these are class members.

Where
const int f();
is a function that returns a const int.
then
SomeClass obj; // can't be const, calling a non const method.
int t = obj.f(); // obj might change
or
const int t = obj.f(); // obj might change


Where
int f() const;
is a function returns an int that will not change the object f() is
called with.
then
SomeClass obj; // could be const if I want.
int t = obj.f(); // obj won't be changed
or
const int t = obj.f(); // obj won't be changed




>> But I'm confused as to why. When you call a ctor with a const
>> reference, that object is, was, already constructed and it's not clear
>> to me that you want to alter the already constructed argument. Or
>> perhaps a slightly different design is what's needed since I think that
>> a copy ctor that alters the argument tends, not always, but tends, to
>> violate the principle of least astonishment. IMO.
>>

> I am astonished. Reference counting seems to be the typical case where
> constness can be broken by necessity, but there are other schemes.
> const means that you agree NOT to modify the argument, which is why
> you have to define const methods if you want to call methods at all!
> It makes for very inefficient programming...


I find that const makes me more efficient, not less.

> The bad C assumption is
> that all you can and want to do with the argument is to copy data, but
> it IS the natural place to perform initializations, management,
> profiling, synchronizations...


For the object that is being constructed.

> because the argument is an OBJECT and
> includes methods. O CloneX() seems to be a valid method to define and
> call in a copy constructor method for members of type O.


Now you've lost me again. But in general, I'd say this depends on what
you want to accomplish. IME, keeping the args to assignment operators
and copy ctors, in fact almost all arguments const, saves me time later.

> ... gcc 4.5.1 seems to keep adding and adding to the language... and
> to the list of BUGS. 4.5.1 means to go through a new installation but
> I got my version bundled. I was reading the known bugs and it seems to
> keep changing things to new features I do not plan to use which
> besides are still buggy!


In my sad experience all compilers have bugs.

> My point is that the code I posted here [AO
> and BO] is such typical and basic C++ it has to compile. The version I
> ve been using exclusively is 3.4.2 I do not want to change it...
> unless it has a real crucial error. Which is what I want to determine.


According to the faq
http://www.parashift.com/c++-faq-lit...t.html#faq-5.9 you
might want to post in gnu.g++.help to get compiler specific help.

LR


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

> On Sep 17, 3:12 pm, Öö Tiib <(E-Mail Removed)> wrote:
>> If you did not declare copy constructor and assignment operator then
>> compiler produces these for you (expect for cases the class was made
>> not copyable). That has been so as long i remember in C++ so i do not
>> get what you complain there.

>
> Indeed, it works automatically and will generate errors if you are
> using pointers and managing your own memory. The AO has also been
> normal C++ as long as I remember but now it is not working well. The
> error message says:
>
> [line] no match for 'operator=' in 'f = BO::Retit()()'
> [line] candidates are AO& operator=(AO&);
>
> !!! Precisely!
>
> 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!
>
> It SEEMS to work with AO:: (const AO &) in BOTH copy constructor and
> assignment operators, the compiler accepts it (compile time),


The difference lies in clause [8.5.3/5]. Temporaries cannot be used to
initialize references _unless_ they are references to const. Hence, a copy
constructor or assignment operator whose argument is a non-const reference
cannot be used with a temporary.

C++0x will introduce rvalue reverences which might help with your problem
should you really need non-const arguments to copy constructor and
assignment operator.

> but const here is almost optional and has been so since ever.

[...]

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


Best

Kai-Uwe Bux
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      09-18-2010
On Sep 17, 8:57 pm, Fabrizio J Bonsignore <(E-Mail Removed)> wrote:
> On Sep 17, 3:12 pm, Öö Tiib <(E-Mail Removed)> wrote:


> > If you did not declare copy constructor and assignment
> > operator then compiler produces these for you (expect for
> > cases the class was made not copyable). That has been so as
> > long i remember in C++ so i do not get what you complain
> > there.


> Indeed, it works automatically and will generate errors if you
> are using pointers and managing your own memory. The AO has
> also been normal C++ as long as I remember but now it is not
> working well. The error message says:


> [line] no match for 'operator=' in 'f = BO::Retit()()'
> [line] candidates are AO& operator=(AO&);


> !!! Precisely!


> 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!


It would help if you'd give more code, instead of just ranting.
But even from just the error messages, I'd guess you're missing
a const in the declarations of the copy constructor and the
assignment operator.

> 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.


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.

> Strictly speaking it is not the same as AO::AO(AO const &x)...
> and you would even have to disambiguate to the extreme of
> AO::AO(const AO const & const a)... and add all variants for
> BOTH assignment and copy constructors!


I'd suggest you learn how const works in C++. Something like
AO::AO(const AO const & const a) is illegal, for two reasons.
And you can bind a non-const object to a reference to const;
usually, the copy constructor and the assignment operator take
references to const, and are not overloaded for non-const.

> In the program this problem arose it is NOT the case: I
> need a SINGLETON, actually I need some UNIQUE reading to propagate
> after initial construction wherever objects of primitive class AO take
> it, UNTIL any of them is Closed(); which means in one scenario (maybe
> at most) I have to discard the reading from the copied object...
> violating the const. It is NOT FUNNY that the suggestion was
> AO::AO(const AO &) and not AO::AO(AO const &) or AO::AO(AO & const);


I'm not sure what you're talking about. AO::AO(const AO&) and
AO::AO(AO const&) are exactly the same thing (and the second is
the prefered way of writing it today), and AO::AO(AO& const) is
illegal (since a reference is always const, and can't be
declared const).

> the latter variants did not compile!


The last shouldn't. The other two should (and do with every
compiler I've ever used).

> This code here is trivial and does nothing, but in real code I
> cannot truly know if I can honor ANY constness in the argument
> object!


That's an unusual case. It's likely a design error (since you'd
be modifying a temporary, which will be immediately destroyed),
but there are exceptions, most of which can be fairly easily
handled by an appropriate use of mutable.

> Which means the risk of needing to defining different
> signatures with almost identical code to handle all
> possibilities!


I have yet to see any case where it made sense to overload the
copy constructor on const-ness.

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


You can't take the address of a temporary (unless you provide a
user defined operator&). It's not allowed by the language.

> but the problem is still the insistence of g++ 3.4.2 in
> finding AO::AO(AO) (!) when later it would say it IS an
> illegal copy constructor signature.


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.

--
James Kanze
 
Reply With Quote
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-19-2010
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...

>
> > 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! There s where I got stopped. Actually it
makes sense: the temporary, or anonymous variable, MUST keep existing
til the end of the current out-of-returning-function statement or the
data gets completely lost! And there is no reason why the memory
address should become invalid AFTER entering the same statement, which
happens to be... a copy constructor defined with a pointer argument!
At what point should the function-returned byvalue copy be destroyed?
The problem is still that this idiom seems to imply there was in
implicit copy constructor called in between, from the in-function
built object to the copy out-of-return-function that reaches the next,
copy constructor method and ends as argument to the next method code.
If the returned object, in the stack frame, is the same from WITHIN
the previous call and INTO the next call, no problema! The address is
valid. In effect the copy constructor gets the right data, though
something tells me that entering the new, non inlined, copy-
constructor-from-pointer, the stack frame should have been modified,
should contain ONLY this and address-of-object and... oops! But the
actual contents of the previous frame are NOT defined in the stack
itself! Unless there is a system (C++) call to **garbage collecting**
in between frame changes the data should STILL be... in the memory
area of the previous frame in the stack! This seems to be the actual
event, but no guarantee it will ALWAYS happen the same for all
classes, all returning functions and all copy constructors from
temporary pointer! Or is there? If the stack frame is actually a stack
and contains frames objects, when will that memory be overwritten? I
do not want to go so deeply into C++ compiling workings now! the idiom
that worked let me write something like:

AO a( &(object.method(argument)).functionReturningAO( ) );

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

> You can't take the address of a temporary (unless you provide a
> user defined operator&). *It's not allowed by the language.


Nope, no operator& defined here... though there IS a pointer to object
member object conversion operator defined...[ operator STRUCT*()
{return &member;} ] which should NOT interfere anyway, as there is no
constructor AO::AO(STRUCT...) whatsoever to ambiguate calls for the
compiler, which incidentally has always been kind of a nuisance in the
language to make primitive type like classes... This means more
testing... but the AO example is simpler and does have the same error
message.

>
> 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.

Danilo J Bonsignore
 
Reply With Quote
 
Fabrizio J Bonsignore
Guest
Posts: n/a
 
      09-19-2010
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... 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. 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**.

Danilo J Bonsignore
 
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