Topic: arrays v. synthesized methods


Author: jimad@microsoft.com (Jim Adcock)
Date: Wed, 26 Jan 1994 19:44:38 GMT
Raw View
In article <1994Jan19.215907.2454@Synopsys.Com> jbuck@synopsys.com (Joe Buck) writes:
|"q.C", line 16: sorry, not implemented: copy of  B[], no memberwise copy for B
|
|It's unclear what to do in this case.  One can generate code that
|calls the copy constructor once for each array element, but it does
|seem that you can't write this operation in C++.  If the array is solely
|primitive objects, as in Jason's original example, the obvious
|solution (copy using assignment) seems fine.

Even with primitives, I'd hope the 'obvious' solution would be
copy using copy construction, but you'd probably complain that
I was being pendantic again....

Let me query you about an interesting meta case.  Consider if the
array is an array of enums.  How should the copy then be performed?

|I recall Jim Adcock complaining about this issue a while back: what
|does memberwise copy mean for array members?  I think some in the
|group thought he was just being pedantic and the solution is obvious.
|Maybe it isn't.

Of course the solution is obvious: C++ OUGHT to support complete
type arrays [arrays whose size is specified at compile-time] as
first class objects:

 typedef double quad[4];

 quad q1, q2;

 ....

 quad q3(q2);

 q1 = q3;

There is no problem with this extension.  It is a pure extension.
When C added assignment and initialization between structures,
assignment and initialization should have been added at the same time.
It was not added, presumably because of continuing confusion
between pointers and arrays.  [For example f(quad q) is implicitly
retyped to be a ptr to double] Now that C++ has added references
this confusion need not continue to apply.

This is what the committee OUGHT to do.  What they will do
[if anything] is stick yet on another nonorthogonal special case bandaid.
Note in particular, the current rules do not handle elements of arrays
because the individual elements of an array are not members -- only
the whole array is.  You can tell the elements are not members because
you cannot have a member pointer to the individual element.  [Likewise,
a base part of an object cannot be a member by the same reasoning]

So, again, there is currently a hole in the definition of the
language regards arrays as members, which needs to be fixed somehow.
You can't just follow the "C" convention of bitwise copying, because
the public/private/protected rights of the cctor and/or assignment
of the class of the element needs to be respected.  To respect these
rights [if and only if applicable] the language needs to define
precisely HOW the array member is cctored or assigned.  Only then
can a compiler know if the protection rights have been violated.
Only then can a compiler generate 'correct' code....




Author: jbuck@synopsys.com (Joe Buck)
Date: Wed, 19 Jan 1994 21:59:07 GMT
Raw View
jason@cygnus.com (Jason Merrill) writes asking about the generation of
copy constructors for objects with arrays.

>struct A {
>  int foo[2];
>};
>...

>Does the default copy constructor use semantics that cannot
>be expressed by a user-defined copy constructor?  Note that Cfront does not
>complain about using copy constructor syntax to initialize an object of
>type A.

No, it appears to generate a bitwise copy in this case, but if you
change the example slightly, to

struct B {
public:
 B();
 B(const B&);
};

struct A {
 B foo[2];
};

int func(A);

int main() {
 A x;
 return func(x);
}

Then cfront 3.0.1 prints

"q.C", line 16: sorry, not implemented: copy of  B[], no memberwise copy for B

It's unclear what to do in this case.  One can generate code that
calls the copy constructor once for each array element, but it does
seem that you can't write this operation in C++.  If the array is solely
primitive objects, as in Jason's original example, the obvious
solution (copy using assignment) seems fine.

I recall Jim Adcock complaining about this issue a while back: what
does memberwise copy mean for array members?  I think some in the
group thought he was just being pedantic and the solution is obvious.
Maybe it isn't.





--
-- Joe Buck jbuck@synopsys.com
Posting from but not speaking for Synopsys, Inc.
Formerly jbuck@<various-hosts>.eecs.berkeley.edu




Author: jason@cygnus.com (Jason Merrill)
Date: Tue, 18 Jan 1994 00:43:17 GMT
Raw View
In reference to the synthesized X::operator=(X&) and X::X(X&) methods, 12.8
says:

"...they will if possible be automatically defined as memberwise assignment
and memberwise initialization of the base classes and non-static data
members of X, respectively."

However, given a class looking like

struct A {
  int foo[2];
};

you can't have a function

A& A::operator=(const A& a) { foo = a.foo; }

right?  I don't see anything about a meaning of op= for arrays in 5.17.
Now, for op= this isn't a problem; the compiler can generate something like

A::A(const A& a) {
  for (int i = 0; i < 2; i++)
    foo[i] = a.foo[i];
}

but what do you do for the copy constructor?

A::A(const A& a): foo[0](a.foo[0]), foo[1](a.foo[1]) { }

doesn't work.  Does the default copy constructor use semantics that cannot
be expressed by a user-defined copy constructor?  Note that Cfront does not
complain about using copy constructor syntax to initialize an object of
type A.

I'm reluctant to suggest the introduction of a default meaning for
initialization and assignment of arrays, due to the automatic promotion to
pointers, but...

Jason