Array copying technique

V

Victor Bazarov

Below you will find some code I wrote to see if I could wrap array copying
(especially for multi-dimensional arrays) in a simple class and/or
function. It seems to work fine for one-dimensioned arrays as well as
two-dimensioned ones. I am sure three- or more-dimensioned array are just
as OK here.

My concern was that I couldn't use 'std::copy' to copy multi-dimensional
arrays. Perhaps in the future we'll see specialisations of 'std::copy'
function that will work with multidimensional arrays similarly to the
'arrcpy' function. [I intentionally named 'arrcpy' that way to indicate
that the arguments are similar to 'strcpy', first the destination, then
the source.]

I've not managed to make this code accept a constant array (or array of
const T), simply because it would probably require a cast for one of the
placement new operators. But in most cases it doesn't matter. Extend it
if you need to.

I am putting it here because I think you might want to comment on it. If
you think you could use it, use it. If you think you have seen something
like this before, do mention it. I am not claiming any innovation here,
just my laziness to look for something similar that has been already done.

Regards,

Victor

cut here 8<-------------------------------------------------- >8 cut here

#include <memory> // for placement new

template<class T, size_t N> struct AC
{
struct W
{
T arr[N];
};

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}
~AC() { *w1 = *w2; }

W *w1, *w2;
};

template<class T, size_t N> void arrcpy(T (&ar1)[N], T (&ar2)[N])
{
AC<T,N> ac(&ar1, &ar2);
}

int main()
{
int ai[1000] = { 1,2,3 };
int bi[1000] = { 5,6,7 };
double a[100][10] = { 1,2,3 };
double b[100][10] = { 5,6,7 };

arrcpy(ai, bi);
arrcpy(a, b);

return 0;
}

cut here 8<-------------------------------------------------- >8 cut here
 
R

Roland Pibinger

Below you will find some code I wrote to see if I could wrap array copying [...]
I am putting it here because I think you might want to comment on it.
cut here 8<-------------------------------------------------- >8 cut here

#include <memory> // for placement new

template<class T, size_t N> struct AC
{
struct W
{
T arr[N];
};

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}
this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
ar1)) said:
~AC() { *w1 = *w2; }

W *w1, *w2;
};

template<class T, size_t N> void arrcpy(T (&ar1)[N], T (&ar2)[N])
{
AC<T,N> ac(&ar1, &ar2);
}

Otherwise it should work.

Best regards,
Roland Pibinger
 
V

Victor Bazarov

Roland said:
Below you will find some code I wrote to see if I could wrap array copying
[...]

I am putting it here because I think you might want to comment on it.

cut here 8<-------------------------------------------------- >8 cut here

#include <memory> // for placement new

template<class T, size_t N> struct AC
{
struct W
{
T arr[N];
};

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}

this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
~AC() { *w1 = *w2; }

W *w1, *w2;
};

template<class T, size_t N> void arrcpy(T (&ar1)[N], T (&ar2)[N])
{
AC<T,N> ac(&ar1, &ar2);
}


Otherwise it should work.

Thanks, Roland. What do you think is the advantage of using the
reinterpret_cast over using placement new?

BTW, I found where it would not work very well (I am sure that some kind
of compile time assertion should help catch those):

if sizeof(W) != sizeof(arr)

IOW, if to create a struct W some padding is required, copying structs
will cause memory overrun, undefined behaviour.

V
 
R

Roland Pibinger

Roland said:
AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}

this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
ar1)),w2(reinterpret_cast<W*> (ar2)) {}

Thanks, Roland. What do you think is the advantage of using the
reinterpret_cast over using placement new?

You actually perform a reinterpret_cast with placement new :), it's
even less safe than reinterpret_cast. You can cast any type to any
other type in C and C++ (not that I recommend that). Why not use the
'idiomatic' approach?
BTW, I found where it would not work very well (I am sure that some kind
of compile time assertion should help catch those):

if sizeof(W) != sizeof(arr)

IOW, if to create a struct W some padding is required, copying structs
will cause memory overrun, undefined behaviour.

Yes, in theory. Padding can only occur at the end in this case. Are
compilers allowed to padd at the end of a struct?

Best wishes,
Roland Pibinger
 
M

Mike Wahler

Roland Pibinger said:
On Tue, 13 Dec 2005 17:01:11 -0500, Victor Bazarov


Yes, in theory. Padding can only occur at the end in this case. Are
compilers allowed to padd at the end of a struct?

Yes, padding is allowed after any struct member (but not before the first).

For some implementations this behavior is configurable (e.g. with
a #pragma).

-Mike
 
V

Victor Bazarov

Roland said:
Roland said:
On Mon, 12 Dec 2005 14:28:42 -0500, Victor Bazarov

AC(T (*ar1)[N], T (*ar2)[N]) : w1(new (ar1) W), w2(new (ar2) W) {}

this should probably be:
AC(T (*ar1)[N], T (*ar2)[N]) : w1 (reinterpret_cast<W*>
ar1)),w2(reinterpret_cast<W*> (ar2)) {}

Thanks, Roland. What do you think is the advantage of using the
reinterpret_cast over using placement new?


You actually perform a reinterpret_cast with placement new :), it's
even less safe than reinterpret_cast.

Could you please elaborate on safety, since you've mentioned it? Thanks!
> You can cast any type to any
other type in C and C++ (not that I recommend that). Why not use the
'idiomatic' approach?

Why would 'reinterpret_cast' be more idiomatic than 'placement new'?
I try to always follow the rule: when constructing an object, even if it
is a POD object, use 'new' unless there is a compelling reason not to.
So, if functionally they are equivalent, I don't see the reason to prefer
the cast.
Yes, in theory. Padding can only occur at the end in this case. Are
compilers allowed to padd at the end of a struct?

What's so special about the end? 5.3.3 speaks about any padding needed
for placing objects of that type in an array, so if there are special
alignment requirements for a struct (can there be?), then we may end up
with some additional space between objects (added after the end of 'arr'
member)...

V
 

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

Members online

Forum statistics

Threads
473,780
Messages
2,569,609
Members
45,254
Latest member
Top Crypto TwitterChannel

Latest Threads

Top