Assignment operator=/copy constructor/temporaries, BROKEN!

  • Thread starter Fabrizio J Bonsignore
  • Start date

F

Fabrizio J Bonsignore

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-
operator=(Function())] because it is a double initialization! I want
a COPY CONSTRUCTOR to be invoked under MY control, to make the NEW AO
x become initialized with the returned old value from Function(). It
happens that AO is a very complex abstraction of the world and
Function() returns a lengthy user process construct with lots of
values obtained from different sources and under different conditions
with lots of very processed and prepared fields and I want to further
process them in another scope in the application, so going through TWO
initializations, default constructor and assignment operator is just
overkill! I cannot simply copy bitwise because AO has the objective of
managing memory, ascertain an object is unique, store memory, and has
side effects like filling in GUI lists and painting in memory stecils
and... I understand that the object returned by **value** from
Function() is a temporary and anonymous memory address that will go
away at any moment out of my control, so I cannot take addresses and
modifying the calling argument in another function makes no sense (in
the absence of side effects) so const is not really necessary nor an
issue, BUT, I need to hold on to the memory of THAT complex instance
and that is the meaning of x! The copy constructor knows what to do
with its own class of objects, it knows what fields are just copied,
which ones initialized from default, which ones need CLONING(), which
ones require new memory before copying them, what complex lot of
processes to place under the rug and take out of the way so that the
user code looks clean and readable and maintainable, etc. But the
compiler is complaining if the copy constructor is programmed
explicitly! It does not accept both assignment operator= and explicit
copy constructor (EXPLICIT means EXPLICITLY PROGRAMMED, not a
hypothetical redundant keyword when implicit means not even mentioned
because bitwise copy is done automatically). I already tried several
combinations: the g++ compiler gets confsed with an illegal AO::AO(AO)
constructor signature! It does not accept BOTH assignment and copy
methods. I can workaround with idiot, I mean, idiom, AO(AO *);
[pointer argument copy constructor] and AO x = &Function(); [address
of temporary!], but it is NOT the C++ I knew for a decade+! Should be
simple and obvious that the returned temporary value has to subsist
til at LEAST the end of this (next) statement! Or function return
values become impossible! Which IS the point of OOP anyway: to handle
data as bundles along its methods and forget about details so complex
data can be handled as easily as arithmetic numbers. But NO! The
compiler is broken, and worse, I cannot see when it happened nor am
really sure it is not some hidden flag, make idiosincracy, weird name
clash, memory corruption, unwanted update or what (at least NOT
without wasting a lot of time like writing this complaint). I ve been
reading other people s call for help on the same problem and the
replies miss the issue, or the case is not exactly the same. Neither
explicit nor const affect the issue: the issue is the compiler looking
for illegal AO::AO(AO) and complaining for legal AO::AO(AO&) methods.
Similar problem with operator=(AO... both as pass-by-reference and
pass-by-value. The best documentation of a system is ALWAYS the system
itself! And its own standard, so any other written standard is just
ideal reality in the future and a goal to achieve IF at all possible!
Version I used is g++ 3.4.2. It was working and got broken, but I want
it to work in THIS project as is. I need a solution or a technical
explanation of why the compiler parser is complaining about looking
for AO::AO(AO) when it also says it is illegal when TO ALL MEANS
AO::AO(AO &) is TOTALLY equivalent and even stronger (should have
preference), and why it complaints if BOTH assignment= and copy
constructor methods are EXPLICITLY DEFINED (programmed). Changing to a
new version is not the best solution... there may be other issues and
so far no known bug has had an impact in this code, so if it is not
broken, do not fix it! But fix this problem, please. (BTW, mofeel.net
means in SPANISH: ...mocked the web).

Danilo J Bonsignore
 
Ad

Advertisements

F

Fabrizio J Bonsignore

I can use as a workaround a very verbose AO &Function() {static AO
AO_Function_return_var; ... return AO_Function_return_var;} Then I can
write without any danger AO x = Function(); and BOTH signatures, the
called function AO &Function(); and the copy constructor AO::AO(AO &);
will have a LITERALLY MATCHING SIGNATURE! Like in AO::AO((AO &)(AO
&)Function()); so both (AO &) terms cancel each other out AS IF this
was a mathematical algebra... but it is a VERY verbose solution and
besides it calls now for TRIPLE initialization! One for an empty AO
object to operate on, an assignment operator= call to re-initialize
the AO_Function_return_var object and FINALLY the correctly called
copy constructor for final result AO object x. This would have SOME
sense in a multithreading environment where access to the static
variables is the synchronization point, but at the cost of triple
initialization. Of course, WITHIN a same object, I do not even need
return types in functions! All functions become void F(); and all
operations are called on member variabled, but that is going BACK to
functional languages only lumped together in a different way! Then
treating it all as memory addresses (pointers) is an error prone
technique IF all return values have to be pointers! The code becomes
dirty with calls to delete and new and the chance of mismatching them
and/or not freeing memory in a web of function calls returning memory
addresses only.

Danilo J Bonsignore
 
G

Goran

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->operator=(Function())] because it is a double initialization! I want

a COPY CONSTRUCTOR to be invoked under MY control, to make the NEW AO
x become initialized with the returned old value from Function(). It
happens that AO is a very complex abstraction of the world and
Function() returns a lengthy user process construct with lots of
values obtained from different sources and under different conditions
with lots of very processed and prepared fields and I want to further
process them in another scope in the application, so going through TWO
initializations, default constructor and assignment operator is just
overkill!

Come down... You seem to want this:

typedef std::auto_ptr<AO> PAO;

PAO Function(irrelevant...)
{
PAO retval(new AO(irrelevant...));
prepare(*retval);
return retval;
}

This is similar to what is happening in Java/.NET world.

If copy-creation and copying of AO are expensive, you can easily
forbid them in C++ (simplest way: derive it from boost::noncopyable).
Also, you probably need to understand the rule of three of C and C++:

http://en.wikipedia.org/wiki/Rule_of_three_(C++_programming)

Goran.
 
F

Fabrizio J Bonsignore

Come down... You seem to want this:

I am DOWN, stucked in a compiling problem.
typedef std::auto_ptr<AO> PAO;

I said: pointers no, there is a pointer workaround but I need to know
why the compiler is rejecting the copy constructor looking for a non
definable signature.
This is similar to what is happening in Java/.NET world.

I want C++, not Java nor .NET (whatever it is) nor any Java-C hybrid.

Rule of three, all right, THAT, is what is BROKEN, in this project AT
LEAST. Seems another project I have is accepting the code as I know it
but then produces errors in another unrelated area. Already tried
equalizing compiler flags but no, the compiler insists in ignoring the
**law of three**, which incidentally seems very suspicious when you do
have a decade and a half programming C++.

I do NOT want to FORBID expensive copying, I want to CONTROL IT. I do
not want to use boost, it is overhead-overkill (my searches and
backups break on the boost zip). In fact, if I do NOT want copying
and assignment, I DO NOT DEFINE THEM! Basically if I do not want them
I do not use them and it is clear by context the object has to be
totted around as a pointer (ie, window objects in Windows), but then
the system would produce spureous versions of the constructors! Seems
like this area of the language went SO ABSTRACT and STANDARD that it
did not touch CURRENT PRACTIVE and WORKING CASES. But then I am using
a downloadable compiler which seems to be far from an industrial heavy
some other provider s version.

Danilo J Bonsignore
 
F

Fabrizio J Bonsignore

I want this to be compilable and working AS IS:

class AO
{
public:
int i;
void Aha();// {i=1;}

AO &operator=(AO &x);// {i=x.i; return *this;}//should not matter if
inline or not

AO();// : i(0) {}
AO(AO &x);// {i=x.i;}
virtual ~AO();// {}
};

void AO::Aha() {
i=1;
}

AO::AO()
: i(0) {
}
AO::AO(AO &x) {
i=x.i;
}
AO &AO::eek:perator=(AO &x) {
i=x.i;
return *this;
}
AO::~AO() {}

class BO
{
AO a;
public:

AO Retit();// {++a.i; return a;}
AO Retut();// {AO z; z.i = 10; return z;}
BO();
};

BO::BO() {
AO b;
b = a;
AO c(a);
AO d(b);
AO e(c);

a.Aha();
b.Aha();
c.Aha();
d.Aha();
e.Aha();

AO m = Retit();
AO n = Retit();
AO o(Retit());
AO p = n;
AO q = o;

AO f;
AO g = Retut();
AO h(Retut());
AO j = g;
AO k = h;

f = Retit();
f = Retut();
}

AO BO::Retit() {
++a.i;
return a;
}
AO BO::Retut() {
AO z;
z.i = 10;
return z;
}


BO testbo;

Danilo J Bonsignore
 
Ad

Advertisements

L

LR

Fabrizio said:
I am DOWN, stucked in a compiling problem.


I said: pointers no, there is a pointer workaround but I need to know
why the compiler is rejecting the copy constructor looking for a non
definable signature.

Can you please post the name of the compiler you are using and a very
small complete example that shows the error message you are getting.

I want C++, not Java nor .NET (whatever it is) nor any Java-C hybrid.


Rule of three, all right, THAT, is what is BROKEN, in this project AT
LEAST. Seems another project I have is accepting the code as I know it
but then produces errors in another unrelated area. Already tried
equalizing compiler flags but no, the compiler insists in ignoring the
**law of three**, which incidentally seems very suspicious when you do
have a decade and a half programming C++.

I do NOT want to FORBID expensive copying, I want to CONTROL IT. I do
not want to use boost, it is overhead-overkill (my searches and
backups break on the boost zip). In fact, if I do NOT want copying
and assignment, I DO NOT DEFINE THEM!

Perhaps you ought to declare the copy ctor and assignment operator as
private and not give them bodies. At least this will verify at linkage
that you aren't using them.

LR
 
F

Francesco S. Carta

I want this to be compilable and working AS IS:

<snip original code>

Well, not exactly as is, as I had to fix some overly long one-line
comments and as I had to add some const here and there, but now it
compiles...

....hope that helps.

//-------
#include <iostream>

class AO {
public:
int i;
void Aha();// {i=1;}

AO &operator=(const AO &x);
// {i=x.i; return *this;}//should not matter if inline or not

AO();// : i(0) {}
AO(const AO &x);// {i=x.i;}
virtual ~AO();// {}
};

void AO::Aha() {
i=1;
}

AO::AO()
: i(0) {
}
AO::AO(const AO &x) {
i=x.i;
}
AO &AO::eek:perator=(const AO &x) {
i=x.i;
return *this;
}
AO::~AO() {}

class BO {
AO a;
public:

AO Retit();// {++a.i; return a;}
AO Retut();// {AO z; z.i = 10; return z;}
BO();
};

BO::BO() {
AO b;
b = a;
AO c(a);
AO d(b);
AO e(c);

a.Aha();
b.Aha();
c.Aha();
d.Aha();
e.Aha();

AO m = Retit();
AO n = Retit();
AO o(Retit());
AO p = n;
AO q = o;

AO f;
AO g = Retut();
AO h(Retut());
AO j = g;
AO k = h;

f = Retit();
f = Retut();
}

AO BO::Retit() {
++a.i;
return a;
}

AO BO::Retut() {
AO z;
z.i = 10;
return z;
}

BO testbo;

using namespace std;

int main() {
cout << "Well, it compiles." << endl;
return 0;
}
//-------
 
L

LR

Fabrizio said:
I want this to be compilable and working AS IS:

I made a few minor changes, but seems to compile, link and run.
class AO
{
public:
int i;
void Aha();// {i=1;}

AO &operator=(AO &x);// {i=x.i; return *this;}//should not matter if
inline or not

What is the concern about the assignment operator being inline?
AO();// : i(0) {}
AO(AO &x);// {i=x.i;}
virtual ~AO();// {}


virtual? Why?
};

void AO::Aha() {
i=1;
}

AO::AO()
: i(0) {
}
AO::AO(AO &x) {
i=x.i;
}

AO::AO(const AO &x)
:
i(x.i)
{}

I prefer my copy ctors to have const arguments and I prefer an
initialization list.

AO &AO::eek:perator=(AO &x) {
i=x.i;
return *this;
}
AO::~AO() {}

class BO
{
AO a;
public:

AO Retit();// {++a.i; return a;}
AO Retut();// {AO z; z.i = 10; return z;}
BO();
};

BO::BO() {
BO::BO()
:
a()
{

AO b;
b = a;
AO c(a);
AO d(b);
AO e(c);

a.Aha();
b.Aha();
c.Aha();
d.Aha();
e.Aha();

AO m = Retit();
AO n = Retit();
AO o(Retit());
AO p = n;
AO q = o;

AO f;
AO g = Retut();
AO h(Retut());
AO j = g;
AO k = h;

f = Retit();
f = Retut();
}

AO BO::Retit() {
++a.i;
return a;
}

I think I'm somewhat missing the point of what you want to do. That code
is going to call a copy ctor. Is that what you want?
AO BO::Retut() {
AO z;
z.i = 10;
return z;
}


BO testbo;

Does the compiler you're using have some sort of optimization flag?
Perhaps it's trying to optimize too much?

What compilation error messages, linkage errors, or runtime errors are
you getting?

Again, can you please tell us what compiler you are using and post a
small complete example that demonstrates the problem you are having.

LR
 
Ö

Öö Tiib

[rant]

It it is hard to understand what code on what compiler, where and for
what purpose you use. Better post code, it is hopefully less whiny. Be
a man, speak like a man, not like hurt alien of some sort. It is
usenet. Your own grandchildren may one day read it.

Feels that you want to make a constructor of class outside of class.
That is impossible and so you have to assign or copy construct
whatever you there constructed.

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

Fabrizio J Bonsignore

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
 
Ad

Advertisements

J

Johannes Schaub (litb)

Fabrizio said:
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...
 
L

LR

Fabrizio said:
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
 
F

Fabrizio J Bonsignore

Oops!

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!
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++).
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.
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.
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.
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...)!
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
 
F

Fabrizio J Bonsignore

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
 
L

LR

Fabrizio said:
Oops!

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.

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



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-lite/how-to-post.html#faq-5.9 you
might want to post in gnu.g++.help to get compiler specific help.

LR
 
Ad

Advertisements

K

Kai-Uwe Bux

Fabrizio said:
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 (1998).


Best

Kai-Uwe Bux
 
J

James Kanze

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

Fabrizio J Bonsignore

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

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
 
Ad

Advertisements

F

Fabrizio J Bonsignore

Fabrizio said:
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 (1998).

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top