Topic: Defining offsetof for trivially-copyable types
Author: Myriachan <myriachan@gmail.com>
Date: Fri, 5 Sep 2014 20:38:44 -0700 (PDT)
Raw View
------=_Part_9102_758348640.1409974724033
Content-Type: text/plain; charset=UTF-8
As a simplification of my thread "Usability extensions to offsetof", I
propose extending the definition of offsetof to state that it is defined
for all trivially-copyable types as well as all standard-layout types--with
the exception that using offsetof on members of reference type would remain
undefined. This is on the basis that an implementation in which offsetof
would not work on trivially-copyable types but would work on
standard-layout types would necessarily violate some other part of the
Standard, or at the least be completely absurd.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_9102_758348640.1409974724033
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">As a simplification of my thread "Usability extensions to =
offsetof", I propose extending the definition of offsetof to state that it =
is defined for all trivially-copyable types as well as all standard-layout =
types--with the exception that using offsetof on members of reference type =
would remain undefined. This is on the basis that an implementation i=
n which offsetof would not work on trivially-copyable types but would work =
on standard-layout types would necessarily violate some other part of the S=
tandard, or at the least be completely absurd.<br><br>Melissa<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_9102_758348640.1409974724033--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 06 Sep 2014 00:03:07 -0700
Raw View
On Friday 05 September 2014 20:38:44 Myriachan wrote:
> As a simplification of my thread "Usability extensions to offsetof", I
> propose extending the definition of offsetof to state that it is defined
> for all trivially-copyable types as well as all standard-layout types--with
> the exception that using offsetof on members of reference type would remain
> undefined. This is on the basis that an implementation in which offsetof
> would not work on trivially-copyable types but would work on
> standard-layout types would necessarily violate some other part of the
> Standard, or at the least be completely absurd.
I'm interested in the rationale for this. What are you trying to access that
is in a trivially-copyable but not standard layout structure?
Types aren't standard layout if they or one of their bases:
1. have a reference, which you excluded
2. have virtual functions, but if they do they aren't trivially copyable
3. have non-static data members with different access control
4. have data members in more than one class in the hierarchy
5. have a base class with the same type as the first data member
I'm guessing you wanted 3. I'm wondering if you're aware of the side-effects of
enabling 4 and 5
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Myriachan <myriachan@gmail.com>
Date: Mon, 8 Sep 2014 02:27:34 -0700 (PDT)
Raw View
------=_Part_7173_1246901572.1410168454467
Content-Type: text/plain; charset=UTF-8
On Saturday, September 6, 2014 12:03:15 AM UTC-7, Thiago Macieira wrote:
>
> I'm interested in the rationale for this. What are you trying to access
> that
> is in a trivially-copyable but not standard layout structure?
>
> Types aren't standard layout if they or one of their bases:
> 1. have a reference, which you excluded
> 2. have virtual functions, but if they do they aren't trivially copyable
> 3. have non-static data members with different access control
> 4. have data members in more than one class in the hierarchy
> 5. have a base class with the same type as the first data member
>
6. have a virtual base class, but if they do the derived type isn't
trivially copyable
> I'm guessing you wanted 3. I'm wondering if you're aware of the
> side-effects of
> enabling 4 and 5
>
For #1: I meant that offsetof(C, r) for reference member R &r in C would be
ill-formed, but offsetof(C, m) for non-reference member M m in C would not
necessarily be. In other words, the presence of a reference would not
"taint" a class from being used with offsetof; only that reference would be
prohibited.
For #3: It was for both #3 and #4 that it'd be convenient. I know that the
compiler can reorder non-standard-layout types however it wants, but to me,
that's a "*caveat programmator*" thing. Member order in a structure would
be implementation-defined/unspecified in non-standard-layout
trivially-copyable types I believe, but an ordering has to exist.
For #4: Hmm, I really don't know of any special rules regarding having
multiple classes in the hierarchy with data members, other than the obvious
ones. What would be a problem?
For #5: I didn't know this rule until I looked it up just now. My
understanding of the rule is that there is only a special case when that
base class is empty. But in that case, the only special thing is that the
offset of that first member cannot be zero, if I understand it correctly.
It did make me notice something interesting, though, that I'll keep in mind
for the future: even standard-layout trivially-copyable classes can
potentially get into trouble if code tries to memcpy a trivially-copyable
class that happens to be empty, and their destination happens to be of
dynamic derived type rather than the base class type. It'll overwrite at
least part of whatever the first member happens to be (unless it's a copy
of the base type).
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7173_1246901572.1410168454467
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, September 6, 2014 12:03:15 AM UTC-7, Thiago M=
acieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I'm interested i=
n the rationale for this. What are you trying to access that=20
<br>is in a trivially-copyable but not standard layout structure?
<br>
<br>Types aren't standard layout if they or one of their bases:
<br>1. have a reference, which you excluded
<br>2. have virtual functions, but if they do they aren't trivially copyabl=
e
<br>3. have non-static data members with different access control
<br>4. have data members in more than one class in the hierarchy
<br>5. have a base class with the same type as the first data member
<br></blockquote><div><br>6. have a virtual base class, but if they do the =
derived type isn't trivially copyable<br> </div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;">I'm guessing you wanted 3. I'm wondering if you're a=
ware of the side-effects of=20
<br>enabling 4 and 5
<br></blockquote><div><br>For #1: I meant that offsetof(C, r) for reference=
member R &r in C would be ill-formed, but offsetof(C, m) for non-refer=
ence member M m in C would not necessarily be. In other words, the pr=
esence of a reference would not "taint" a class from being used with offset=
of; only that reference would be prohibited.<br><br>For #3: It was for both=
#3 and #4 that it'd be convenient. I know that the compiler can reor=
der non-standard-layout types however it wants, but to me, that's a "<i>cav=
eat programmator</i>" thing. Member order in a structure would be imp=
lementation-defined/unspecified in non-standard-layout trivially-copyable t=
ypes I believe, but an ordering has to exist.<br><br>For #4: Hmm, I really =
don't know of any special rules regarding having multiple classes in the hi=
erarchy with data members, other than the obvious ones. What would be=
a problem?<br><br>For #5: I didn't know this rule until I looked it up jus=
t now. My understanding of the rule is that there is only a special c=
ase when that base class is empty. But in that case, the only special=
thing is that the offset of that first member cannot be zero, if I underst=
and it correctly.<br><br>It did make me notice something interesting, thoug=
h, that I'll keep in mind for the future: even standard-layout trivially-co=
pyable classes can potentially get into trouble if code tries to memcpy a t=
rivially-copyable class that happens to be empty, and their destination hap=
pens to be of dynamic derived type rather than the base class type. I=
t'll overwrite at least part of whatever the first member happens to be (un=
less it's a copy of the base type).<br><br>Melissa<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7173_1246901572.1410168454467--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 08 Sep 2014 08:49:10 -0700
Raw View
On Monday 08 September 2014 02:27:34 Myriachan wrote:
> It did make me notice something interesting, though, that I'll keep in mind
> for the future: even standard-layout trivially-copyable classes can
> potentially get into trouble if code tries to memcpy a trivially-copyable
> class that happens to be empty, and their destination happens to be of
> dynamic derived type rather than the base class type. It'll overwrite at
> least part of whatever the first member happens to be (unless it's a copy
> of the base type).
Which is probably part of the reason for #4. The other reason is probably use
of tail-padding (which, with some stretch, is the same reason).
Don't copy across types. It only makes sense to copy a variable of dynamic
type X onto another type of the same dynamic type. A very simple thought
example is what happens when Y, deriving from X, is nowhere near standard
layout or triviality (adds virtuals, multiple inheritance, multiple
protection, etc): if you memcpy an X x onto Y y, even with adjusted pointers,
you may be doing something really bad.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?ISO-8859-1?Q?Agust=EDn_K-ballo_Berg=E9?= <kaballo86@hotmail.com>
Date: Mon, 8 Sep 2014 13:19:09 -0300
Raw View
On 08/09/2014 12:49 p.m., Thiago Macieira wrote:
> if you memcpy an X x onto Y y, even with adjusted pointers,
> you may be doing something really bad.
Unless X and Y are layout-compatible, right?
Regards,
--=20
Agust=EDn K-ballo Berg=E9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 08 Sep 2014 09:30:52 -0700
Raw View
On Monday 08 September 2014 13:19:09 Agust=EDn K-ballo Berg=E9 wrote:
> On 08/09/2014 12:49 p.m., Thiago Macieira wrote:
> > if you memcpy an X x onto Y y, even with adjusted pointers,
> > you may be doing something really bad.
>=20
> Unless X and Y are layout-compatible, right?
That's a circular definition. They are layout-compatible if they can be=20
memcpy'ed to/fro.
The point I was trying to make is that X and Y are not layout compatible if=
=20
one derives from the other, and that technically, unfortunately, includes t=
he=20
X subobject in Y.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?ISO-8859-1?Q?Agust=EDn_K-ballo_Berg=E9?= <kaballo86@hotmail.com>
Date: Mon, 8 Sep 2014 13:48:41 -0300
Raw View
On 08/09/2014 01:30 p.m., Thiago Macieira wrote:
> On Monday 08 September 2014 13:19:09 Agust=EDn K-ballo Berg=E9 wrote:
>> On 08/09/2014 12:49 p.m., Thiago Macieira wrote:
>>> if you memcpy an X x onto Y y, even with adjusted pointers,
>>> you may be doing something really bad.
>>
>> Unless X and Y are layout-compatible, right?
>
> That's a circular definition. They are layout-compatible if they can be
> memcpy'ed to/fro.
I was referring to the standard definition of layout-compatible.
> The point I was trying to make is that X and Y are not layout compatible =
if
> one derives from the other, and that technically, unfortunately, includes=
the
> X subobject in Y.
In order for memcpy to be well-defined, both X and Y have to be=20
standard-layout, which requires at least one of them to be empty.=20
According to my reading of the standard, X and Y are:
- if base and derived are both empty, layout-compatible, otherwise
- if derived is empty, layout-compatible, or
- if base is empty, not layout-compatible
So, in the end, whether it is well-defined to memcpy an X into a Y=20
depends exclusively on them being layout-compatible.
Regards,
--=20
Agust=EDn K-ballo Berg=E9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 08 Sep 2014 09:56:26 -0700
Raw View
On Monday 08 September 2014 13:48:41 Agust=EDn K-ballo Berg=E9 wrote:
> > The point I was trying to make is that X and Y are not layout compatibl=
e
> > if
> > one derives from the other, and that technically, unfortunately, includ=
es
> > the X subobject in Y.
>=20
> In order for memcpy to be well-defined, both X and Y have to be
> standard-layout, which requires at least one of them to be empty.
> According to my reading of the standard, X and Y are:
>=20
> - if base and derived are both empty, layout-compatible, otherwise
> - if derived is empty, layout-compatible, or
> - if base is empty, not layout-compatible
>=20
> So, in the end, whether it is well-defined to memcpy an X into a Y
> depends exclusively on them being layout-compatible.
Again, the problem is that X is not layout compatible with X-in-Y:
struct X {};
struct Y : public X { int i; };
sizeof(X) =3D 1 because sizeof can't be zero. However, the empty base X in =
Y=20
occupies zero bytes on most ABIs. You can't do this:
template<typename T> void copy(T *dest, const T *src)
{
static_assert(std::is_standard_layout<T>::value);
memcpy(dest, src, sizeof(T));
}
void doit(Y *dest, X *src)
{
X *pdest =3D dest;
copy(pdest, src);
}
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?ISO-8859-1?Q?Agust=EDn_K-ballo_Berg=E9?= <kaballo86@hotmail.com>
Date: Mon, 8 Sep 2014 14:15:21 -0300
Raw View
On 08/09/2014 01:56 p.m., Thiago Macieira wrote:
> On Monday 08 September 2014 13:48:41 Agust=EDn K-ballo Berg=E9 wrote:
>>> The point I was trying to make is that X and Y are not layout compatibl=
e
>>> if
>>> one derives from the other, and that technically, unfortunately, includ=
es
>>> the X subobject in Y.
>>
>> In order for memcpy to be well-defined, both X and Y have to be
>> standard-layout, which requires at least one of them to be empty.
>> According to my reading of the standard, X and Y are:
>>
>> - if base and derived are both empty, layout-compatible, otherwise
>> - if derived is empty, layout-compatible, or
>> - if base is empty, not layout-compatible
>>
>> So, in the end, whether it is well-defined to memcpy an X into a Y
>> depends exclusively on them being layout-compatible.
>
> Again, the problem is that X is not layout compatible with X-in-Y:
>
> struct X {};
> struct Y : public X { int i; };
Nod, that is the single case that I listed above as not=20
layout-compatible according to the standard. However, in:
struct X { int i; };
struct Y : public X {};
X and Y *are* layout-compatible.
My point being that whether memcpy an X into a Y is well-defined or not=20
does not depend on whether one derives from the other, but on whether=20
the standard says so (that they are layout-compatible). And for=20
completeness and as a disclaimer, the standard does get it wrong in some=20
corner cases.
> sizeof(X) =3D 1 because sizeof can't be zero. However, the empty base X i=
n Y
> occupies zero bytes on most ABIs.
As of C++11 and for this particular example, the empty base will occupy=20
zero bytes in all compliant implementations (the standard requires it).
Regards,
--=20
Agust=EDn K-ballo Berg=E9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Myriachan <myriachan@gmail.com>
Date: Mon, 8 Sep 2014 16:01:20 -0700 (PDT)
Raw View
------=_Part_194_206688241.1410217280286
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 8, 2014 10:15:33 AM UTC-7, Agust=C3=ADn K-ballo Berg=
=C3=A9 wrote:
>
> My point being that whether memcpy an X into a Y is well-defined or not=
=20
> does not depend on whether one derives from the other, but on whether=20
> the standard says so (that they are layout-compatible). And for=20
> completeness and as a disclaimer, the standard does get it wrong in some=
=20
> corner cases.=20
>
The Standard already excludes this case in [basic.types].2: "For any=20
trivially copyable type T, if two pointers to T point to distinct T objects=
=20
obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if=20
the underlying bytes (1.7) making up obj1 are copied into obj2, obj2 shall=
=20
subsequently hold the same value as obj1." By the way, the Standard does=
=20
not mention anywhere a relationship between the defined term "
*layout-compatible*" and std::memcpy. It only talks about how=20
*layout-compatible* implies that reinterpret_cast from one type to the=20
other must work, and for partially layout-compatible classes, that the=20
initial members of the same type and order must properly alias.
The important thing to note about *trivially-copyable* is that there are=20
really only two things that distinguish it from *standard-layout*:=20
differing access control and inheritance with data members at multiple=20
levels in the hierarchy.
Access control only affects the ordering of data members in a class. A=20
class has a maximum of 6 possible orderings of members, the permutations of=
=20
"private", "protected" and "public". Within each access level, the order=
=20
can only be as specified. Regardless of any of this, offsetof is not=20
affected: each member still has a unique, valid, constant offset from the=
=20
beginning of the trivially-copyable class.
Data members at multiple levels of the hierarchy just means that the base=
=20
class subobjects will exist somewhere in the memory space of the dynamic=20
type. The Standard states that the base class subobjects can have a layout=
=20
different from what they'd be as standalone (most-derived) objects=20
([class.derived] 5 and 8). However, by the definition of=20
*trivially-copyable*, the members of all base classes will themselves be=20
trivially copyable, and thus be compatible with memcpy. offsetof cannot=20
refer to the base class subobject, only to the members thereof, so offsetof=
=20
does not break in this circumstance. Because the target of memcpy cannot=
=20
be predicted in advance, the offset of base class subobjects within a=20
derived class must be a constant. (I suppose it could be a link-time or=20
run-time constant instead of compile-time, but that seems like a rather=20
crazy implementation choice.)
By the same argument, the members of a class must be at a constant offset. =
=20
Combining everything above results in the fact that all members accessible=
=20
to offsetof are at a fixed constant offset from the beginning of the=20
most-derived class.
The above makes a fundamental assumption: the assumption that std::memcpy=
=20
is not a magic function. In other words, that the following is a=20
fully-legitimate implementation of memcpy that will always work on every=20
C++ implementation, even in maximum layout and pointer aliasing craziness=
=20
mode:
void *custom_memcpy(void *d, const void *s, std::size_t size)
{
unsigned char *dest =3D static_cast<unsigned char *>(d);
const unsigned char *src =3D static_cast<const unsigned char *(s);
for (; size > 0; --size)
{
*dest++ =3D *src++;
}
return d;
}
The reason for the assumption is that the proof that being=20
trivially-copyable is sufficient for allowing offsetof to work properly=20
relies upon the fact that for every member m of non-reference type M within=
=20
a trivially-copyable class C, there necessarily exists an unsigned char *=
=20
pointing within the unsigned char array representation of C that aliases=20
what gets copied to C::m.
Melissa
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_194_206688241.1410217280286
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, September 8, 2014 10:15:33 AM UTC-7, Agust=C3=
=ADn K-ballo Berg=C3=A9 wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
My point being that whether memcpy an X into a Y is well-defined or not=20
<br>does not depend on whether one derives from the other, but on whether=
=20
<br>the standard says so (that they are layout-compatible). And for=20
<br>completeness and as a disclaimer, the standard does get it wrong in som=
e=20
<br>corner cases.
<br></blockquote><div><br>The Standard already excludes this case in [basic=
..types].2: "For any trivially copyable type <span style=3D"font-family: cou=
rier new,monospace;">T</span>, if two pointers to <span style=3D"font-famil=
y: courier new,monospace;">T</span> point to distinct <span style=3D"font-f=
amily: courier new,monospace;">T</span> objects <span style=3D"font-family:=
courier new,monospace;">obj1</span> and <span style=3D"font-family: courie=
r new,monospace;">obj2</span>, where neither <span style=3D"font-family: co=
urier new,monospace;">obj1</span> nor <span style=3D"font-family: courier n=
ew,monospace;">obj2</span> is a base-class subobject, if the underlying byt=
es (1.7) making up <span style=3D"font-family: courier new,monospace;">obj1=
</span> are copied into <span style=3D"font-family: courier new,monospace;"=
>obj2</span>, <span style=3D"font-family: courier new,monospace;">obj2</spa=
n> shall subsequently hold the same value as <span style=3D"font-family: co=
urier new,monospace;">obj1</span>." By the way, the Standard does not=
mention anywhere a relationship between the defined term "<i>layout-compat=
ible</i>" and <span style=3D"font-family: courier new,monospace;">std::memc=
py</span>. It only talks about how <i>layout-compatible</i> implies t=
hat <span style=3D"font-family: courier new,monospace;">reinterpret_cast</s=
pan> from one type to the other must work, and for partially layout-compati=
ble classes, that the initial members of the same type and order must prope=
rly alias.<br><br>The important thing to note about <i>trivially-copyable</=
i> is that there are really only two things that distinguish it from <i>sta=
ndard-layout</i>: differing access control and inheritance with data member=
s at multiple levels in the hierarchy.<br><br>Access control only affects t=
he ordering of data members in a class. A class has a maximum of 6 po=
ssible orderings of members, the permutations of "<span style=3D"font-famil=
y: courier new,monospace;">private</span>", "<span style=3D"font-family: co=
urier new,monospace;">protected</span>" and "<span style=3D"font-family: co=
urier new,monospace;">public</span>". Within each access level, the o=
rder can only be as specified. Regardless of any of this, <span style=
=3D"font-family: courier new,monospace;">offsetof</span> is not affected: e=
ach member still has a unique, valid, constant offset from the beginning of=
the trivially-copyable class.<br><br>Data members at multiple levels of th=
e hierarchy just means that the base class subobjects will exist somewhere =
in the memory space of the dynamic type. The Standard states that the=
base class subobjects can have a layout different from what they'd be as s=
tandalone (most-derived) objects ([class.derived] 5 and 8). However, =
by the definition of <i>trivially-copyable</i>, the members of all base cla=
sses will themselves be trivially copyable, and thus be compatible with <sp=
an style=3D"font-family: courier new,monospace;">memcpy</span>. <span=
style=3D"font-family: courier new,monospace;">offsetof</span> cannot refer=
to the base class subobject, only to the members thereof, so <span style=
=3D"font-family: courier new,monospace;">offsetof</span> does not break in =
this circumstance. Because the target of <span style=3D"font-family: =
courier new,monospace;">memcpy</span> cannot be predicted in advance, the o=
ffset of base class subobjects within a derived class must be a constant.&n=
bsp; (I suppose it could be a link-time or run-time constant instead of com=
pile-time, but that seems like a rather crazy implementation choice.)<br><b=
r>By the same argument, the members of a class must be at a constant offset=
.. Combining everything above results in the fact that all members acc=
essible to offsetof are at a fixed constant offset from the beginning of th=
e most-derived class.<br><br>The above makes a fundamental assumption: the =
assumption that <span style=3D"font-family: courier new,monospace;">std::me=
mcpy</span> is not a magic function. In other words, that the followi=
ng is a fully-legitimate implementation of <span style=3D"font-family: cour=
ier new,monospace;">memcpy</span> that will always work on every C++ implem=
entation, even in maximum layout and pointer aliasing craziness mode:<br><b=
r><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250);=
border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; =
word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">custom_memcpy</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">d</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">s</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">size_t s=
ize</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">unsigned</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">char</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">dest </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">stat=
ic_cast</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><=
;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">unsigned<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">char</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">*>(</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">d</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">unsigned</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">char</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">src </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">static_cast</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">unsigned</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">char</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">*(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">s</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">for</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> size </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-p=
rettify">0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">--</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">size</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">dest</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">++</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">s=
rc</span><span style=3D"color: #660;" class=3D"styled-by-prettify">++;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> &nbs=
p; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br> &=
nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">retu=
rn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> d</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span></div></code></div><br><br>Th=
e reason for the assumption is that the proof that being trivially-copyable=
is sufficient for allowing <span style=3D"font-family: courier new,monospa=
ce;">offsetof</span> to work properly relies upon the fact that for every m=
ember <span style=3D"font-family: courier new,monospace;">m</span> of non-r=
eference type <span style=3D"font-family: courier new,monospace;">M</span> =
within a trivially-copyable class <span style=3D"font-family: courier new,m=
onospace;">C</span>, there necessarily exists an <span style=3D"font-family=
: courier new,monospace;">unsigned char *</span> pointing within the <span =
style=3D"font-family: courier new,monospace;">unsigned char</span> array re=
presentation of <span style=3D"font-family: courier new,monospace;">C</span=
> that aliases what gets copied to <span style=3D"font-family: courier new,=
monospace;">C::m</span>.<br><br>Melissa<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_194_206688241.1410217280286--
.
Author: =?UTF-8?B?QWd1c3TDrW4gSy1iYWxsbyBCZXJnw6k=?= <kaballo86@hotmail.com>
Date: Mon, 8 Sep 2014 21:04:06 -0300
Raw View
On 08/09/2014 08:01 p.m., Myriachan wrote:
> On Monday, September 8, 2014 10:15:33 AM UTC-7, Agust=C3=ADn K-ballo Berg=
=C3=A9 wrote:
>
> My point being that whether memcpy an X into a Y is well-defined or n=
ot
> does not depend on whether one derives from the other, but on whether
> the standard says so (that they are layout-compatible). And for
> completeness and as a disclaimer, the standard does get it wrong in
> some
> corner cases.
>
>
> The Standard already excludes this case in [basic.types].2: "For any
> trivially copyable type T, if two pointers to T point to distinct T
> objects obj1 and obj2, where neither obj1 nor obj2 is a base-class
> subobject, if the underlying bytes (1.7) making up obj1 are copied into
> obj2, obj2 shall subsequently hold the same value as obj1."
I don't think it does, see below.
> By the way,
> the Standard does not mention anywhere a relationship between the
> defined term "/layout-compatible/" and std::memcpy. It only talks about
> how /layout-compatible/ implies that reinterpret_cast from one type to
> the other must work, and for partially layout-compatible classes, that
> the initial members of the same type and order must properly alias.
Trivially-copyable gives you `std::memcpy`, and as you point out=20
layout-compatible gives you `reinterpret_cast`. They are orthogonal=20
concepts, and when you have them together you get `std::memcpy` across=20
layout-compatible types.
However, depending on your reading of the standard, this might imply=20
that the following is well-defined:
struct X { int i; } x =3D {42};
struct Y : X {} y;
// copy x to y, not base-class subobjects
std::memcpy(&y, reinterpret_cast<Y*>(&x), sizeof(Y));
assert(y.i =3D=3D 42);
while the following isn't:
// copy y back to x, is (X*)&y a base-class subobject?
std::memcpy(reinterpret_cast<X*>(&y), &x, sizeof(X));
assert(x.i =3D=3D 42);
Hopefully someone will point out the flaws in my logic.
> [snipped offsetof discussion]
Regards,
--=20
Agust=C3=ADn K-ballo Berg=C3=A9.-
http://talesofcpp.fusionfenix.com
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Myriachan <myriachan@gmail.com>
Date: Tue, 9 Sep 2014 14:18:44 -0700 (PDT)
Raw View
------=_Part_1274_282600185.1410297524908
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, September 8, 2014 5:04:17 PM UTC-7, Agust=C3=ADn K-ballo Berg=C3=
=A9 wrote:
>
>
> Trivially-copyable gives you `std::memcpy`, and as you point out=20
> layout-compatible gives you `reinterpret_cast`. They are orthogonal=20
> concepts, and when you have them together you get `std::memcpy` across=20
> layout-compatible types.=20
>
> However, depending on your reading of the standard, this might imply=20
> that the following is well-defined:=20
>
> struct X { int i; } x =3D {42};=20
> struct Y : X {} y;=20
>
> // copy x to y, not base-class subobjects=20
> std::memcpy(&y, reinterpret_cast<Y*>(&x), sizeof(Y));=20
> assert(y.i =3D=3D 42);=20
>
> while the following isn't:=20
>
> // copy y back to x, is (X*)&y a base-class subobject?=20
> std::memcpy(reinterpret_cast<X*>(&y), &x, sizeof(X));=20
> assert(x.i =3D=3D 42);=20
>
> Hopefully someone will point out the flaws in my logic.=20
>
>
Well, normally, you'd use static_cast to go between X * and Y *, but=20
anyway...
The first one is well-defined, because X and Y are trivially copyable in=20
addition to standard-layout, and because of this clause ([class.mem].19):
If a standard-layout class object has any non-static data members, its=20
> address is the same as the address of its first non-static data member.=
=20
> Otherwise, its address is the same as the address of its first base class=
=20
> subobject (if any).
>
(This is also why reinterpret_cast works rather than just static_cast for=
=20
the class and not just for &i.)
The second one is defined if and only if the Standard assures that sizeof(X=
)=20
=3D=3D sizeof(Y). Whether this is true is unclear to me; it's certainly=20
implied by "empty base class optimization" and the rule that=20
standard-layout requires that only one class in the DAG have nonstatic data=
=20
members.
Melissa
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1274_282600185.1410297524908
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, September 8, 2014 5:04:17 PM UTC-7, Agust=C3=AD=
n K-ballo Berg=C3=A9 wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><br=
>Trivially-copyable gives you `std::memcpy`, and as you point out=20
<br>layout-compatible gives you `reinterpret_cast`. They are orthogonal=20
<br>concepts, and when you have them together you get `std::memcpy` across=
=20
<br>layout-compatible types.
<br>
<br>However, depending on your reading of the standard, this might imply=20
<br>that the following is well-defined:
<br>
<br> struct X { int i; } x =3D {42};
<br> struct Y : X {} y;
<br>
<br> // copy x to y, not base-class subobjects
<br> std::memcpy(&y, reinterpret_cast<Y*>(&=
;x), sizeof(Y));
<br> assert(y.i =3D=3D 42);
<br>
<br>while the following isn't:
<br>
<br> // copy y back to x, is (X*)&y a base-class sub=
object?
<br> std::memcpy(reinterpret_cast<<wbr>X*>(&y)=
, &x, sizeof(X));
<br> assert(x.i =3D=3D 42);
<br>
<br>Hopefully someone will point out the flaws in my logic.
<br>
<br></blockquote><div><br>Well, normally, you'd use <span style=3D"font-fam=
ily: courier new,monospace;">static_cast</span> to go between <span style=
=3D"font-family: courier new,monospace;">X *</span> and <span style=3D"font=
-family: courier new,monospace;">Y *</span>, but anyway...<br><br>The first=
one is well-defined, because X and Y are trivially copyable in addition to=
standard-layout, and because of this clause ([class.mem].19):<br><br><bloc=
kquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, =
204, 204); padding-left: 1ex;" class=3D"gmail_quote">If a standard-layout c=
lass object has any non-static data members, its address is the same as the=
address of its first non-static data member. Otherwise, its address is the=
same as the address of its first base class subobject (if any).<br></block=
quote><div><br>(This is also why <span style=3D"font-family: courier new,mo=
nospace;">reinterpret_cast</span> works rather than just <span style=3D"fon=
t-family: courier new,monospace;">static_cast</span> for the class and not =
just for <span style=3D"font-family: courier new,monospace;">&i</span>.=
)<br><br>The second one is defined if and only if the Standard assures that=
<span style=3D"font-family: courier new,monospace;">sizeof(X) =3D=3D sizeo=
f(Y)</span>. Whether this is true is unclear to me; it's certainly im=
plied by "empty base class optimization" and the rule that standard-layout =
requires that only one class in the DAG have nonstatic data members.<br><br=
>Melissa<br></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1274_282600185.1410297524908--
.
Author: Myriachan <myriachan@gmail.com>
Date: Wed, 10 Sep 2014 16:38:18 -0700 (PDT)
Raw View
------=_Part_2645_967463721.1410392298521
Content-Type: text/plain; charset=UTF-8
What reasons are there to disallow offsetof on trivially-copyable
non-standard-layout types, given that there exists a well-defined fixed
value that can be assigned to offsetof for all members of all such classes
on all implementations? (Under my no-magic-memcpy assumption.)
References excluded; it's possible to show that a reference member of a
trivially-copyable class must also have a valid fixed offset, but there's
no way to get at it with an offsetof macro, so there's no reason to define
this.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2645_967463721.1410392298521
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">What reasons are there to disallow <span style=3D"font-fam=
ily: courier new,monospace;">offsetof</span> on trivially-copyable non-stan=
dard-layout types, given that there exists a well-defined fixed value that =
can be assigned to <span style=3D"font-family: courier new,monospace;">offs=
etof</span> for all members of all such classes on all implementations?&nbs=
p; (Under my no-magic-<span style=3D"font-family: courier new,monospace;">m=
emcpy</span> assumption.)<br><br>References excluded; it's possible to show=
that a reference member of a trivially-copyable class must also have a val=
id fixed offset, but there's no way to get at it with an <span style=3D"fon=
t-family: courier new,monospace;">offsetof</span> macro, so there's no reas=
on to define this.<br><br>Melissa<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2645_967463721.1410392298521--
.
Author: Myriachan <myriachan@gmail.com>
Date: Wed, 17 Sep 2014 20:51:15 -0700 (PDT)
Raw View
------=_Part_3_2101070040.1411012276043
Content-Type: text/plain; charset=UTF-8
Is a proposal to extend offsetof to trivially-copyable types likely to
fail, or is it something I should trying writing up as a submission? Note
that I've never tried anything like this.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3_2101070040.1411012276043
Content-Type: text/html; charset=UTF-8
<div dir="ltr">Is a proposal to extend offsetof to trivially-copyable types likely to fail, or is it something I should trying writing up as a submission? Note that I've never tried anything like this.<br><br>Melissa<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
------=_Part_3_2101070040.1411012276043--
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Wed, 17 Sep 2014 21:21:10 -0700 (PDT)
Raw View
------=_Part_26_1968506919.1411014070077
Content-Type: text/plain; charset=UTF-8
On Thursday, September 18, 2014 12:51:16 AM UTC-3, Myriachan wrote:
>
> Is a proposal to extend offsetof to trivially-copyable types likely to
> fail, or is it something I should trying writing up as a submission? Note
> that I've never tried anything like this.
>
>
We were discussing in another thread that it should be possible, at least
on some ABIs, to have a trivially_copyable class with virtual base classes.
And so for such a class, it would be possible that for some members you
would know their offset at compile-time, and for others you don't.
In more general terms, currently a class being trivially copyable means two
things, that it's not undefined to memcpy an object of such a class,
and that the copy of such an object represents the same value as the
original.
How does that relate to the concept of having all members with fixed
offsets?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_26_1968506919.1411014070077
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, September 18, 2014 12:51:16 AM UTC-3, Myriach=
an wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Is a=
proposal to extend offsetof to trivially-copyable types likely to fail, or=
is it something I should trying writing up as a submission? Note tha=
t I've never tried anything like this.<br><br></div></blockquote><div><br>W=
e were discussing in another thread that it should be possible, at least on=
some ABIs, to have a trivially_copyable class with virtual base classes.<b=
r>And so for such a class, it would be possible that for some members you w=
ould know their offset at compile-time, and for others you don't.<br><br>In=
more general terms, currently a class being trivially copyable means two t=
hings, that it's not undefined to memcpy an object of such a class,<br>and =
that the copy of such an object represents the same value as the original.<=
br>How does that relate to the concept of having all members with fixed off=
sets?<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_26_1968506919.1411014070077--
.
Author: Myriachan <myriachan@gmail.com>
Date: Thu, 18 Sep 2014 16:51:36 -0700 (PDT)
Raw View
------=_Part_3040_1691672917.1411084297028
Content-Type: text/plain; charset=UTF-8
On Wednesday, September 17, 2014 9:21:10 PM UTC-7, Matheus Izvekov wrote:
>
> On Thursday, September 18, 2014 12:51:16 AM UTC-3, Myriachan wrote:
>>
>> Is a proposal to extend offsetof to trivially-copyable types likely to
>> fail, or is it something I should trying writing up as a submission? Note
>> that I've never tried anything like this.
>>
>>
> We were discussing in another thread that it should be possible, at least
> on some ABIs, to have a trivially_copyable class with virtual base classes.
> And so for such a class, it would be possible that for some members you
> would know their offset at compile-time, and for others you don't.
>
> In more general terms, currently a class being trivially copyable means
> two things, that it's not undefined to memcpy an object of such a class,
> and that the copy of such an object represents the same value as the
> original.
> How does that relate to the concept of having all members with fixed
> offsets?
>
From those two aspects of the definition of trivially copyable, you can
formally prove that the offset must be fixed from at least the time the
first memcpy to an unsigned char array is done. (And it would be rather
absurd for an implementation to fix it *then* as opposed to earlier.)
However, there is an important flaw in the proof, a way in which an
implementation could have a non-constant offset, but I show how ridiculous
it'd have to be.
The proof comes down to the below. (By non-static data member, I include
recursively and in union members, etc.)
First we prove that such an offset always exists:
1. Trivially-copyable types are in contiguous bytes of memory.
2. Trivially-copyable types are defined recursively: all non-static data
members of trivially-copyable types are trivially copyable.
3. By 1 and 2, all non-static data members of trivially-copyable types are
in contiguous bytes of memory.
4. By 3 and because copying the containing type also copies the member, for
each non-static data member, some unique contiguous subsequence of the
unsigned char array representation of the containing type represents it.
5. By 4 and by 2, for each non-static data member, memcpy to or from this
contiguous subsequence is equivalent to copying said member.
6. The starting index of this contiguous subsequence is the offset.
Then we prove that it's necessarily a constant:
1. It's implied by the Standard that so long as the values in the unsigned
char array representation of a trivially-copyable type are the same later
when the memcpy back to an object of the original type is done, bytes of
the unsigned char array can be rearranged and modified as the programmer
chooses. (They can even be separated into separate objects for a time, so
long as they end up later in a single unsigned char array, possibly not the
original array, of at least the type's size with the same contents as
originally.)
2. Assume for contradiction that the offset for a single member of a single
most-derived type is ever different, and equals x at one point and y at
another. By "point" I mean a four-dimensional location, where the
dimensions are location of code, call stack, thread, and time.
3. Write a program:
3a. At a 4-D location at which the offset of member m within
trivially-copyable type T is x, construct t1 and set t1.m to constant M1.
3b. memcpy t1 to unsigned char a1[sizeof(T)].
3c. At a 4-D location at which the offset of member m within
trivially-copyable type T is y, construct t2 and set t2.m to constant M2,
where M2 != M1.
3d. memcpy t2 to unsigned char a2[sizeof(T)].
3e. Print x, y, M1, a1, M2, and a2 to stdout.
3f. Read an int z from stdin.
3g. If z is odd, memcpy a1 into unsigned char a3[sizeof(T)]. If z is even,
memcpy a2 into a3 instead.
3h. memcpy a3 into T a3.
3i. Print a3.m to stdout.
4. With two caveats I will note below, the above program has caused a
contradiction. The observable behavior of the program commits to values of
x, y, a1 and a2 before receiving a choice of which array. The compiler
can't have foreknowledge of where within a3 needs to be read from for m.
Caveat 1: It is conceivably possible in some situations for a
sufficiently-clever compiler to "get away with it", but not in all
situations. For example, if type T has empty space due to padding,
information necessary to survive both directions in the above check could
be stowed away. But this cannot be accomplished in full generality.
Moreover, it is always possible to design a test that will cause the
necessary paradox for even types that have padding like this.
Caveat 2: I suppose that it is possible to define an implementation in
which the offset of a member is specified by hidden fields within a class.
With non-standard-layout classes, a hidden offset field could be placed by
the compiler, and the object's constructors could implicitly set this in a
manner similar to how vtable pointers get initialized. Such an offset
would get copied by memcpy correctly. However, it leads from there to a
difficult implementation: the architecture would have to handle pointers in
a very strange way, because pointers to any member of such a class would
have to magically redirect to a new offset if the offset changed. Although
I suppose such an implementation would be legal, it's also quite
ridiculous, because this code has to work, according to the Standard, as
far as I know:
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <type_traits>
#define Tcbnsl TriviallyCopyableButNotStandardLayout
class Tcbnsl {
protected:
int m_private;
public:
double m_public;
Tcbnsl(int priv) : m_private(priv) { }
};
int main() {
static_assert(std::is_trivially_copyable<Tcbnsl>::value, "type is not
trivially copyable");
Tcbnsl a{1};
a.m_public = 2.0;
Tcbnsl b{0};
b.m_public = 3.0;
unsigned char *public_ptr = reinterpret_cast<unsigned char *>(&b.
m_public);
std::printf("%p\n", public_ptr);
unsigned char public_copy[sizeof(b.m_public)];
std::memcpy(public_copy, &b.m_public, sizeof(b.m_public));
std::memcpy(&b, &a, sizeof(a));
std::memcpy(public_ptr, public_copy, sizeof(public_copy));
std::printf("%g\n%p\n", b.m_public, public_ptr);
return 0;
}
In order to support m_public's offset not being constant, the
implementation would have to magically handle the value of public_ptr
needing to point to somewhere else after that second-to-last memcpy, even
though the value of the pointer is no different. Note that the
implementation has to support this even though public_ptr could also be
temporarily be obfuscated in a mangled std::uintptr_t somewhere.
In short, this is kind of silly, and such an implementation should not be a
reason to not have offsetof for all trivially-copyable types.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3040_1691672917.1411084297028
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, September 17, 2014 9:21:10 PM UTC-7, Matheus=
Izvekov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
">On Thursday, September 18, 2014 12:51:16 AM UTC-3, Myriachan wrote:<block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Is a proposal to extend =
offsetof to trivially-copyable types likely to fail, or is it something I s=
hould trying writing up as a submission? Note that I've never tried a=
nything like this.<br><br></div></blockquote><div><br>We were discussing in=
another thread that it should be possible, at least on some ABIs, to have =
a trivially_copyable class with virtual base classes.<br>And so for such a =
class, it would be possible that for some members you would know their offs=
et at compile-time, and for others you don't.<br><br>In more general terms,=
currently a class being trivially copyable means two things, that it's not=
undefined to memcpy an object of such a class,<br>and that the copy of suc=
h an object represents the same value as the original.<br>How does that rel=
ate to the concept of having all members with fixed offsets?<br></div></div=
></blockquote><div><br>From those two aspects of the definition of triviall=
y copyable, you can formally prove that the offset must be fixed from at le=
ast the time the first <span style=3D"font-family: courier new,monospace;">=
memcpy</span> to an <span style=3D"font-family: courier new,monospace;">uns=
igned char</span> array is done. (And it would be rather absurd for a=
n implementation to fix it <i>then</i> as opposed to earlier.) Howeve=
r, there is an important flaw in the proof, a way in which an implementatio=
n could have a non-constant offset, but I show how ridiculous it'd have to =
be.<br><br>The proof comes down to the below. (By non-static data mem=
ber, I include recursively and in union members, etc.)<br><br>First we prov=
e that such an offset always exists:<br><br>1. Trivially-copyable types are=
in contiguous bytes of memory.<br>2. Trivially-copyable types are defined =
recursively: all non-static data members of trivially-copyable types are tr=
ivially copyable.<br>3. By 1 and 2, all non-static data members of triviall=
y-copyable types are in contiguous bytes of memory.<br>4. By 3 and because =
copying the containing type also copies the member, for each non-static dat=
a member, some unique contiguous subsequence of the unsigned char array rep=
resentation of the containing type represents it.<br>5. By 4 and by 2, for =
each non-static data member, <span style=3D"font-family: courier new,monosp=
ace;">memcpy</span> to or from this contiguous subsequence is equivalent to=
copying said member.<br>6. The starting index of this contiguous subsequen=
ce is the offset.<br><br>Then we prove that it's necessarily a constant:<br=
><br>1. It's implied by the Standard that so long as the values in the unsi=
gned char array representation of a trivially-copyable type are the same la=
ter when the <span style=3D"font-family: courier new,monospace;">memcpy</sp=
an> back to an object of the original type is done, bytes of the <span styl=
e=3D"font-family: courier new,monospace;">unsigned char</span> array can be=
rearranged and modified as the programmer chooses. (They can even be=
separated into separate objects for a time, so long as they end up later i=
n a single <span style=3D"font-family: courier new,monospace;">unsigned cha=
r</span> array, possibly not the original array, of at least the type's siz=
e with the same contents as originally.)<br>2. Assume for contradiction tha=
t the offset for a single member of a single most-derived type is ever diff=
erent, and equals <span style=3D"font-family: courier new,monospace;">x</sp=
an> at one point and <span style=3D"font-family: courier new,monospace;">y<=
/span> at another. By "point" I mean a four-dimensional location, whe=
re the dimensions are location of code, call stack, thread, and time.<br>3.=
Write a program:<br>3a. At a 4-D location at which the offset of member <s=
pan style=3D"font-family: courier new,monospace;">m</span> within trivially=
-copyable type <span style=3D"font-family: courier new,monospace;">T</span>=
is <span style=3D"font-family: courier new,monospace;">x</span>, construct=
<span style=3D"font-family: courier new,monospace;">t1</span> and set <spa=
n style=3D"font-family: courier new,monospace;">t1.m</span> to constant <sp=
an style=3D"font-family: courier new,monospace;">M1</span>.<br>3b. <span st=
yle=3D"font-family: courier new,monospace;">memcpy</span> <span style=3D"fo=
nt-family: courier new,monospace;">t1</span> to <span style=3D"font-family:=
courier new,monospace;">unsigned char a1[sizeof(T)]</span>.<br>3c. At a 4-=
D location at which the offset of member <span style=3D"font-family: courie=
r new,monospace;">m</span> within=20
trivially-copyable type <span style=3D"font-family: courier new,monospace;"=
>T</span> is <span style=3D"font-family: courier new,monospace;">y</span>, =
construct <span style=3D"font-family: courier new,monospace;">t2</span> and=
set <span style=3D"font-family: courier new,monospace;">t2.m</span> to con=
stant <span style=3D"font-family: courier new,monospace;">
M2</span>, where <span style=3D"font-family: courier new,monospace;">M2 !=
=3D M1</span>.<br>3d. <span style=3D"font-family: courier new,monospace;">m=
emcpy</span> <span style=3D"font-family: courier new,monospace;">t2</span> =
to <span style=3D"font-family: courier new,monospace;">unsigned char a2[siz=
eof(T)]</span>.<br>3e. Print <span style=3D"font-family: courier new,monosp=
ace;">x</span>, <span style=3D"font-family: courier new,monospace;">y</span=
>, <span style=3D"font-family: courier new,monospace;">M1</span>, <span sty=
le=3D"font-family: courier new,monospace;">a1</span>, <span style=3D"font-f=
amily: courier new,monospace;">M2</span>, and <span style=3D"font-family: c=
ourier new,monospace;">a2</span> to <span style=3D"font-family: courier new=
,monospace;">stdout</span>.<br>3f. Read an <span style=3D"font-family: cour=
ier new,monospace;">int z</span> from <span style=3D"font-family: courier n=
ew,monospace;">stdin</span>.<br>3g. If <span style=3D"font-family: courier =
new,monospace;">z</span> is odd, <span style=3D"font-family: courier new,mo=
nospace;">memcpy</span> <span style=3D"font-family: courier new,monospace;"=
>a1</span> into <span style=3D"font-family: courier new,monospace;">unsigne=
d char a3[sizeof(T)]</span>. If <span style=3D"font-family: courier n=
ew,monospace;">z</span> is even, <span style=3D"font-family: courier new,mo=
nospace;">memcpy</span> <span style=3D"font-family: courier new,monospace;"=
>a2</span> into <span style=3D"font-family: courier new,monospace;">a3</spa=
n> instead.<br>3h. <span style=3D"font-family: courier new,monospace;">memc=
py</span> <span style=3D"font-family: courier new,monospace;">a3</span> int=
o <span style=3D"font-family: courier new,monospace;">T a3</span>.<br>3i. P=
rint <span style=3D"font-family: courier new,monospace;">a3.m</span> to <sp=
an style=3D"font-family: courier new,monospace;">stdout</span>.<br>4. With =
two caveats I will note below, the above program has caused a contradiction=
.. The observable behavior of the program commits to values of <span s=
tyle=3D"font-family: courier new,monospace;">x</span>, <span style=3D"font-=
family: courier new,monospace;">y</span>, <span style=3D"font-family: couri=
er new,monospace;">a1</span> and <span style=3D"font-family: courier new,mo=
nospace;">a2</span> before receiving a choice of which array. The com=
piler can't have foreknowledge of where within <span style=3D"font-family: =
courier new,monospace;">a3</span> needs to be read from for m.<br><br>Cavea=
t 1: It is conceivably possible in some situations for a sufficiently-cleve=
r compiler to "get away with it", but not in all situations. For exam=
ple, if type <span style=3D"font-family: courier new,monospace;">T</span> h=
as empty space due to padding, information necessary to survive both direct=
ions in the above check could be stowed away. But this cannot be acco=
mplished in full generality. Moreover, it is always possible to desig=
n a test that will cause the necessary paradox for even types that have pad=
ding like this.<br><br>Caveat 2: I suppose that it is possible to define an=
implementation in which the offset of a member is specified by hidden fiel=
ds within a class. With non-standard-layout classes, a hidden offset =
field could be placed by the compiler, and the object's constructors could =
implicitly set this in a manner similar to how vtable pointers get initiali=
zed. Such an offset would get copied by <span style=3D"font-family: c=
ourier new,monospace;">memcpy</span> correctly. However, it leads fro=
m there to a difficult implementation: the architecture would have to handl=
e pointers in a very strange way, because pointers to any member of such a =
class would have to magically redirect to a new offset if the offset change=
d. Although I suppose such an implementation would be legal, it's als=
o quite ridiculous, because this code has to work, according to the Standar=
d, as far as I know:<br><br><div class=3D"prettyprint" style=3D"background-=
color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: =
solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprin=
t"><div class=3D"subprettyprint"><span style=3D"color: #800;" class=3D"styl=
ed-by-prettify">#include</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-prett=
ify"><cstdint></span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: #800;" class=3D"styled-by-pretti=
fy">#include</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify"><cst=
dio></span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span><span style=3D"color: #800;" class=3D"styled-by-prettify">#include<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #080;" class=3D"styled-by-prettify"><cstring></spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">#include</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #080;" class=3D"styled-by-prettify"><type_traits></span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span st=
yle=3D"color: #800;" class=3D"styled-by-prettify">#define</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Tcbnsl</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">TriviallyCopyableButNotStandardLayout</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Tcbnsl</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">protected</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&=
nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> m_p=
rivate</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">public</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">double</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> m_public</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br><br> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Tcbnsl</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> priv</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
m_private</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">priv</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">i=
nt</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> main</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">static_assert</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">is_trivially_copyable</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #606;=
" class=3D"styled-by-prettify">Tcbnsl</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">>::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">value</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify"=
>"type is not trivially copyable"</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br><br> </span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Tcbnsl</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #066;" class=3D"styled-by-pre=
ttify">1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">};=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">m_public <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #066;" class=3D"styled-by-prettify">2.0</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br> <br> </span>=
<span style=3D"color: #606;" class=3D"styled-by-prettify">Tcbnsl</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br> b</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">m_public </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-pretti=
fy">3.0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> &=
nbsp; <br> </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">unsigned</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">char</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">public_ptr </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">unsigned</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">char</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">*>(&</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">b</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">m_=
public</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> &=
nbsp; std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">printf</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
style=3D"color: #080;" class=3D"styled-by-prettify">"%p\n"</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> public_ptr</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br> <br> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">unsigned</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">char</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> public_copy</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">sizeof</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">b</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">m_public</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">)];</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
> std</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
memcpy</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">public_copy</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">b</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">m_public</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">b</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">m_public</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">));</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br> <br>  =
; std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">memcpy</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(&</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">b</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">a</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">siz=
eof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">a</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">));</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br> <br> &nb=
sp; std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">memcpy</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">public_ptr</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> public_copy</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">sizeof</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">public_copy</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br> std</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">printf</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">"=
%g\n%p\n"</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">m_public</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> public_ptr</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" cla=
ss=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan></div></code></div><br>In order to support <span style=3D"font-family: =
courier new,monospace;">m_public</span>'s offset not being constant, the im=
plementation would have to magically handle the value of <span style=3D"fon=
t-family: courier new,monospace;">public_ptr</span> needing to point to som=
ewhere else after that second-to-last <span style=3D"font-family: courier n=
ew,monospace;">memcpy</span>, even though the value of the pointer is no di=
fferent. Note that the implementation has to support this even though=
<span style=3D"font-family: courier new,monospace;">public_ptr</span> coul=
d also be temporarily be obfuscated in a mangled <span style=3D"font-family=
: courier new,monospace;">std::uintptr_t</span> somewhere.<br><br>In short,=
this is kind of silly, and such an implementation should not be a reason t=
o not have <span style=3D"font-family: courier new,monospace;">offsetof</sp=
an> for all trivially-copyable types.<br><br>Melissa<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3040_1691672917.1411084297028--
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Thu, 18 Sep 2014 19:49:52 -0700 (PDT)
Raw View
------=_Part_2075_1801994015.1411094992635
Content-Type: text/plain; charset=UTF-8
On Thursday, September 18, 2014 8:51:37 PM UTC-3, Myriachan wrote:
>
>
> From those two aspects of the definition of trivially copyable, you can
> formally prove that the offset must be fixed from at least the time the
> first memcpy to an unsigned char array is done.
>
Actually, on your proof that follows, you only try to address the first
aspect, and not the second one. The point still remains that it is
arbitrary to tie offsetof to is_trivially_copyable since they are unrelated
concepts, even if it were the case that you could define offsetof for those
in almost all circumstances.
The current definition in the standard at least has the justification that
it's trying to allow it only for C compatible types.
Instead, I would suggest you try to start from scratch and try to define it
in terms of more basic concepts.
I have three separate initial suggestions, and I will list them in order
starting from safest and then on to most potentially dangerous.
1) Define offsetof as valid for all types which recursively don't contain
classes with virtual inheritance.
I think this would be the most broad category where all member offsets
would be well defined, and they would be usable with both pointers to whole
objects as well as to incomplete objects. This could possibly exclude
taking the offset of member references.
2) Define offsetof for types which might recursively contain classes with
virtual inheritance, but disallow taking the offset of members which are
contained in virtually inherited subobjects, since those offsets would not
be usable with pointers to incomplete objects.
This would be the most complete definition that is still relatively
safe, but it would add the caveat that now offsetof might be allowed for
some members but not others, which is something that does not happen
currently in the standard. (currently when offsetof is defined for a type,
then it is defined for all members of such type)
3) As above, but allow taking the offset of members which are contained in
virtually inherited subobjects. This one is pretty unsafe, as such offsets
would only be usable with pointers to whole objects.
> (And it would be rather absurd for an implementation to fix it *then*
> as opposed to earlier.) However, there is an important flaw in the proof,
> a way in which an implementation could have a non-constant offset, but I
> show how ridiculous it'd have to be.
>
> The proof comes down to the below. (By non-static data member, I include
> recursively and in union members, etc.)
>
> First we prove that such an offset always exists:
>
> 1. Trivially-copyable types are in contiguous bytes of memory.
> 2. Trivially-copyable types are defined recursively: all non-static data
> members of trivially-copyable types are trivially copyable.
> 3. By 1 and 2, all non-static data members of trivially-copyable types are
> in contiguous bytes of memory.
> 4. By 3 and because copying the containing type also copies the member,
> for each non-static data member, some unique contiguous subsequence of the
> unsigned char array representation of the containing type represents it.
> 5. By 4 and by 2, for each non-static data member, memcpy to or from this
> contiguous subsequence is equivalent to copying said member.
> 6. The starting index of this contiguous subsequence is the offset.
>
> Then we prove that it's necessarily a constant:
>
> 1. It's implied by the Standard that so long as the values in the unsigned
> char array representation of a trivially-copyable type are the same later
> when the memcpy back to an object of the original type is done, bytes of
> the unsigned char array can be rearranged and modified as the programmer
> chooses. (They can even be separated into separate objects for a time, so
> long as they end up later in a single unsigned char array, possibly not
> the original array, of at least the type's size with the same contents as
> originally.)
> 2. Assume for contradiction that the offset for a single member of a
> single most-derived type is ever different, and equals x at one point and
> y at another. By "point" I mean a four-dimensional location, where the
> dimensions are location of code, call stack, thread, and time.
> 3. Write a program:
> 3a. At a 4-D location at which the offset of member m within
> trivially-copyable type T is x, construct t1 and set t1.m to constant M1.
> 3b. memcpy t1 to unsigned char a1[sizeof(T)].
> 3c. At a 4-D location at which the offset of member m within
> trivially-copyable type T is y, construct t2 and set t2.m to constant M2,
> where M2 != M1.
> 3d. memcpy t2 to unsigned char a2[sizeof(T)].
> 3e. Print x, y, M1, a1, M2, and a2 to stdout.
> 3f. Read an int z from stdin.
> 3g. If z is odd, memcpy a1 into unsigned char a3[sizeof(T)]. If z is
> even, memcpy a2 into a3 instead.
> 3h. memcpy a3 into T a3.
> 3i. Print a3.m to stdout.
> 4. With two caveats I will note below, the above program has caused a
> contradiction. The observable behavior of the program commits to values of
> x, y, a1 and a2 before receiving a choice of which array. The compiler
> can't have foreknowledge of where within a3 needs to be read from for m.
>
> Caveat 1: It is conceivably possible in some situations for a
> sufficiently-clever compiler to "get away with it", but not in all
> situations. For example, if type T has empty space due to padding,
> information necessary to survive both directions in the above check could
> be stowed away. But this cannot be accomplished in full generality.
> Moreover, it is always possible to design a test that will cause the
> necessary paradox for even types that have padding like this.
>
> Caveat 2: I suppose that it is possible to define an implementation in
> which the offset of a member is specified by hidden fields within a class.
> With non-standard-layout classes, a hidden offset field could be placed by
> the compiler, and the object's constructors could implicitly set this in a
> manner similar to how vtable pointers get initialized. Such an offset
> would get copied by memcpy correctly. However, it leads from there to a
> difficult implementation: the architecture would have to handle pointers in
> a very strange way, because pointers to any member of such a class would
> have to magically redirect to a new offset if the offset changed. Although
> I suppose such an implementation would be legal, it's also quite
> ridiculous, because this code has to work, according to the Standard, as
> far as I know:
>
> #include <cstdint>
> #include <cstdio>
> #include <cstring>
> #include <type_traits>
>
> #define Tcbnsl TriviallyCopyableButNotStandardLayout
> class Tcbnsl {
> protected:
> int m_private;
> public:
> double m_public;
>
> Tcbnsl(int priv) : m_private(priv) { }
> };
>
> int main() {
> static_assert(std::is_trivially_copyable<Tcbnsl>::value, "type is not
> trivially copyable");
>
> Tcbnsl a{1};
> a.m_public = 2.0;
>
> Tcbnsl b{0};
> b.m_public = 3.0;
>
> unsigned char *public_ptr = reinterpret_cast<unsigned char *>(&b.
> m_public);
> std::printf("%p\n", public_ptr);
>
> unsigned char public_copy[sizeof(b.m_public)];
> std::memcpy(public_copy, &b.m_public, sizeof(b.m_public));
>
> std::memcpy(&b, &a, sizeof(a));
>
> std::memcpy(public_ptr, public_copy, sizeof(public_copy));
> std::printf("%g\n%p\n", b.m_public, public_ptr);
> return 0;
> }
>
> In order to support m_public's offset not being constant, the
> implementation would have to magically handle the value of public_ptr
> needing to point to somewhere else after that second-to-last memcpy, even
> though the value of the pointer is no different. Note that the
> implementation has to support this even though public_ptr could also be
> temporarily be obfuscated in a mangled std::uintptr_t somewhere.
>
> In short, this is kind of silly, and such an implementation should not be
> a reason to not have offsetof for all trivially-copyable types.
>
> Melissa
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2075_1801994015.1411094992635
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, September 18, 2014 8:51:37 PM UTC-3, Myriacha=
n wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
<br>From those two aspects of the definition of trivially copyable, you can=
formally prove that the offset must be fixed from at least the time the fi=
rst <span style=3D"font-family:courier new,monospace">memcpy</span> to an <=
span style=3D"font-family:courier new,monospace">unsigned char</span> array=
is done.</div></div></blockquote><div><br>Actually, on your proof that fol=
lows, you only try to address the first aspect, and not the second one. The=
point still remains that it is arbitrary to tie offsetof to is_trivially_c=
opyable since they are unrelated concepts, even if it were the case that yo=
u could define offsetof for those in almost all circumstances.<br>The curre=
nt definition in the standard at least has the justification that it's tryi=
ng to allow it only for C compatible types.<br><br>Instead, I would suggest=
you try to start from scratch and try to define it in terms of more basic =
concepts.<br><br>I have three separate initial suggestions, and I will list=
them in order starting from safest and then on to most potentially dangero=
us.<br><br>1) Define offsetof as valid for all types which recursively don'=
t contain classes with virtual inheritance.<br> I t=
hink this would be the most broad category where all member offsets would b=
e well defined, and they would be usable with both pointers to whole object=
s as well as to incomplete objects. This could possibly exclude taking the =
offset of member references.<br><br>2) Define offsetof for types which migh=
t recursively contain classes with virtual inheritance, but disallow taking=
the offset of members which are contained in virtually inherited subobject=
s, since those offsets would not be usable with pointers to incomplete obje=
cts.<br> This would be the most complete definition=
that is still relatively safe, but it would add the caveat that now offset=
of might be allowed for some members but not others, which is something tha=
t does not happen currently in the standard. (currently when offsetof is de=
fined for a type, then it is defined for all members of such type)<br><br>3=
) As above, but allow taking the offset of members which are contained in =
virtually inherited subobjects. This one is pretty unsafe, as such offsets =
would only be usable with pointers to whole objects.<br><br><br><br> <=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>&nb=
sp; (And it would be rather absurd for an implementation to fix it <i>then<=
/i> as opposed to earlier.) However, there is an important flaw in th=
e proof, a way in which an implementation could have a non-constant offset,=
but I show how ridiculous it'd have to be.<br><br>The proof comes down to =
the below. (By non-static data member, I include recursively and in u=
nion members, etc.)<br><br>First we prove that such an offset always exists=
:<br><br>1. Trivially-copyable types are in contiguous bytes of memory.<br>=
2. Trivially-copyable types are defined recursively: all non-static data me=
mbers of trivially-copyable types are trivially copyable.<br>3. By 1 and 2,=
all non-static data members of trivially-copyable types are in contiguous =
bytes of memory.<br>4. By 3 and because copying the containing type also co=
pies the member, for each non-static data member, some unique contiguous su=
bsequence of the unsigned char array representation of the containing type =
represents it.<br>5. By 4 and by 2, for each non-static data member, <span =
style=3D"font-family:courier new,monospace">memcpy</span> to or from this c=
ontiguous subsequence is equivalent to copying said member.<br>6. The start=
ing index of this contiguous subsequence is the offset.<br><br>Then we prov=
e that it's necessarily a constant:<br><br>1. It's implied by the Standard =
that so long as the values in the unsigned char array representation of a t=
rivially-copyable type are the same later when the <span style=3D"font-fami=
ly:courier new,monospace">memcpy</span> back to an object of the original t=
ype is done, bytes of the <span style=3D"font-family:courier new,monospace"=
>unsigned char</span> array can be rearranged and modified as the programme=
r chooses. (They can even be separated into separate objects for a ti=
me, so long as they end up later in a single <span style=3D"font-family:cou=
rier new,monospace">unsigned char</span> array, possibly not the original a=
rray, of at least the type's size with the same contents as originally.)<br=
>2. Assume for contradiction that the offset for a single member of a singl=
e most-derived type is ever different, and equals <span style=3D"font-famil=
y:courier new,monospace">x</span> at one point and <span style=3D"font-fami=
ly:courier new,monospace">y</span> at another. By "point" I mean a fo=
ur-dimensional location, where the dimensions are location of code, call st=
ack, thread, and time.<br>3. Write a program:<br>3a. At a 4-D location at w=
hich the offset of member <span style=3D"font-family:courier new,monospace"=
>m</span> within trivially-copyable type <span style=3D"font-family:courier=
new,monospace">T</span> is <span style=3D"font-family:courier new,monospac=
e">x</span>, construct <span style=3D"font-family:courier new,monospace">t1=
</span> and set <span style=3D"font-family:courier new,monospace">t1.m</spa=
n> to constant <span style=3D"font-family:courier new,monospace">M1</span>.=
<br>3b. <span style=3D"font-family:courier new,monospace">memcpy</span> <sp=
an style=3D"font-family:courier new,monospace">t1</span> to <span style=3D"=
font-family:courier new,monospace">unsigned char a1[sizeof(T)]</span>.<br>3=
c. At a 4-D location at which the offset of member <span style=3D"font-fami=
ly:courier new,monospace">m</span> within=20
trivially-copyable type <span style=3D"font-family:courier new,monospace">T=
</span> is <span style=3D"font-family:courier new,monospace">y</span>, cons=
truct <span style=3D"font-family:courier new,monospace">t2</span> and set <=
span style=3D"font-family:courier new,monospace">t2.m</span> to constant <s=
pan style=3D"font-family:courier new,monospace">
M2</span>, where <span style=3D"font-family:courier new,monospace">M2 !=3D =
M1</span>.<br>3d. <span style=3D"font-family:courier new,monospace">memcpy<=
/span> <span style=3D"font-family:courier new,monospace">t2</span> to <span=
style=3D"font-family:courier new,monospace">unsigned char a2[sizeof(T)]</s=
pan>.<br>3e. Print <span style=3D"font-family:courier new,monospace">x</spa=
n>, <span style=3D"font-family:courier new,monospace">y</span>, <span style=
=3D"font-family:courier new,monospace">M1</span>, <span style=3D"font-famil=
y:courier new,monospace">a1</span>, <span style=3D"font-family:courier new,=
monospace">M2</span>, and <span style=3D"font-family:courier new,monospace"=
>a2</span> to <span style=3D"font-family:courier new,monospace">stdout</spa=
n>.<br>3f. Read an <span style=3D"font-family:courier new,monospace">int z<=
/span> from <span style=3D"font-family:courier new,monospace">stdin</span>.=
<br>3g. If <span style=3D"font-family:courier new,monospace">z</span> is od=
d, <span style=3D"font-family:courier new,monospace">memcpy</span> <span st=
yle=3D"font-family:courier new,monospace">a1</span> into <span style=3D"fon=
t-family:courier new,monospace">unsigned char a3[sizeof(T)]</span>. I=
f <span style=3D"font-family:courier new,monospace">z</span> is even, <span=
style=3D"font-family:courier new,monospace">memcpy</span> <span style=3D"f=
ont-family:courier new,monospace">a2</span> into <span style=3D"font-family=
:courier new,monospace">a3</span> instead.<br>3h. <span style=3D"font-famil=
y:courier new,monospace">memcpy</span> <span style=3D"font-family:courier n=
ew,monospace">a3</span> into <span style=3D"font-family:courier new,monospa=
ce">T a3</span>.<br>3i. Print <span style=3D"font-family:courier new,monosp=
ace">a3.m</span> to <span style=3D"font-family:courier new,monospace">stdou=
t</span>.<br>4. With two caveats I will note below, the above program has c=
aused a contradiction. The observable behavior of the program commits=
to values of <span style=3D"font-family:courier new,monospace">x</span>, <=
span style=3D"font-family:courier new,monospace">y</span>, <span style=3D"f=
ont-family:courier new,monospace">a1</span> and <span style=3D"font-family:=
courier new,monospace">a2</span> before receiving a choice of which array.&=
nbsp; The compiler can't have foreknowledge of where within <span style=3D"=
font-family:courier new,monospace">a3</span> needs to be read from for m.<b=
r><br>Caveat 1: It is conceivably possible in some situations for a suffici=
ently-clever compiler to "get away with it", but not in all situations.&nbs=
p; For example, if type <span style=3D"font-family:courier new,monospace">T=
</span> has empty space due to padding, information necessary to survive bo=
th directions in the above check could be stowed away. But this canno=
t be accomplished in full generality. Moreover, it is always possible=
to design a test that will cause the necessary paradox for even types that=
have padding like this.<br><br>Caveat 2: I suppose that it is possible to =
define an implementation in which the offset of a member is specified by hi=
dden fields within a class. With non-standard-layout classes, a hidde=
n offset field could be placed by the compiler, and the object's constructo=
rs could implicitly set this in a manner similar to how vtable pointers get=
initialized. Such an offset would get copied by <span style=3D"font-=
family:courier new,monospace">memcpy</span> correctly. However, it le=
ads from there to a difficult implementation: the architecture would have t=
o handle pointers in a very strange way, because pointers to any member of =
such a class would have to magically redirect to a new offset if the offset=
changed. Although I suppose such an implementation would be legal, i=
t's also quite ridiculous, because this code has to work, according to the =
Standard, as far as I know:<br><br><div style=3D"background-color:rgb(250,2=
50,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;w=
ord-wrap:break-word"><code><div><span style=3D"color:#800">#include</span><=
span style=3D"color:#000"> </span><span style=3D"color:#080"><cstdint>=
;</span><span style=3D"color:#000"><br></span><span style=3D"color:#800">#i=
nclude</span><span style=3D"color:#000"> </span><span style=3D"color:#080">=
<cstdio></span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#800">#include</span><span style=3D"color:#000"> </span><span style=3D=
"color:#080"><cstring></span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#800">#include</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#080"><type_traits></span><span style=3D"color:#=
000"><br><br></span><span style=3D"color:#800">#define</span><span style=3D=
"color:#000"> </span><span style=3D"color:#606">Tcbnsl</span><span style=3D=
"color:#000"> </span><span style=3D"color:#606">TriviallyCopyableButNotStan=
dar<wbr>dLayout</span><span style=3D"color:#000"><br></span><span style=3D"=
color:#008">class</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#606">Tcbnsl</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#008">protected</span><span style=3D"color:#660">:</span><span style=3D"=
color:#000"><br> </span><span style=3D"color:#008">int</span><=
span style=3D"color:#000"> m_private</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#008">public<=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>&nb=
sp; </span><span style=3D"color:#008">double</span><span style=3D"co=
lor:#000"> m_public</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br><br> </span><span style=3D"color:#606">Tcbnsl=
</span><span style=3D"color:#660">(</span><span style=3D"color:#008">int</s=
pan><span style=3D"color:#000"> priv</span><span style=3D"color:#660">)</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><s=
pan style=3D"color:#000"> m_private</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">priv</span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span=
style=3D"color:#000"> </span><span style=3D"color:#660">}</span><span styl=
e=3D"color:#000"><br></span><span style=3D"color:#660">};</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">int</span><span s=
tyle=3D"color:#000"> main</span><span style=3D"color:#660">()</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br> </span><span style=3D"color:#008">static_=
assert</span><span style=3D"color:#660">(</span><span style=3D"color:#000">=
std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">is=
_<wbr>trivially_copyable</span><span style=3D"color:#660"><</span><span =
style=3D"color:#606">Tcbnsl</span><span style=3D"color:#660">>::</span><=
span style=3D"color:#000">va<wbr>lue</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#080">"type is n=
ot trivially copyable"</span><span style=3D"color:#660">);</span><span styl=
e=3D"color:#000"><br><br> </span><span style=3D"color:#606">Tc=
bnsl</span><span style=3D"color:#000"> a</span><span style=3D"color:#660">{=
</span><span style=3D"color:#066">1</span><span style=3D"color:#660">};</sp=
an><span style=3D"color:#000"><br> a</span><span style=3D"colo=
r:#660">.</span><span style=3D"color:#000">m_public </span><span style=3D"c=
olor:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#066">2.0</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br> <br> </span><span style=3D"color:#606">=
Tcbnsl</span><span style=3D"color:#000"> b</span><span style=3D"color:#660"=
>{</span><span style=3D"color:#066">0</span><span style=3D"color:#660">};</=
span><span style=3D"color:#000"><br> b</span><span style=3D"co=
lor:#660">.</span><span style=3D"color:#000">m_public </span><span style=3D=
"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#066">3.0</span><span style=3D"color:#660">;</span><span style=3D"color=
:#000"><br> <br> </span><span style=3D"color:#008=
">unsigned</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">char</span><span style=3D"color:#000"> </span><span style=3D"color:#660=
">*</span><span style=3D"color:#000">public_ptr </span><span style=3D"color=
:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">reinterpret_cast</span><span style=3D"color:#660"><</span><span styl=
e=3D"color:#008">unsigned</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">char</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">*>(&</span><span style=3D"color:#000">b</span><span=
style=3D"color:#660">.</span><span style=3D"color:#000">m_public</span><sp=
an style=3D"color:#660">);</span><span style=3D"color:#000"><br> &nbs=
p; std</span><span style=3D"color:#660">::</span><span style=3D"color:#000"=
>printf</span><span style=3D"color:#660">(</span><span style=3D"color:#080"=
>"%p\n"</span><span style=3D"color:#660">,</span><span style=3D"color:#000"=
> public_ptr</span><span style=3D"color:#660">);</span><span style=3D"color=
:#000"><br> <br> </span><span style=3D"color:#008=
">unsigned</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">char</span><span style=3D"color:#000"> public_copy</span><span style=3D=
"color:#660">[</span><span style=3D"color:#008">sizeof</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">b</span><span style=3D"colo=
r:#660">.</span><span style=3D"color:#000">m_public</span><span style=3D"co=
lor:#660">)<wbr>];</span><span style=3D"color:#000"><br> std</=
span><span style=3D"color:#660">::</span><span style=3D"color:#000">memcpy<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">public_=
copy</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#660">&</span><span style=3D"color:#000">b</=
span><span style=3D"color:#660">.</span><span style=3D"color:#000">m_public=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">sizeof</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">b</span><span style=3D"color:#660">.</span><sp=
an style=3D"color:#000">m_public</span><span style=3D"color:#660">));</span=
><span style=3D"color:#000"><br> <br> std</span><=
span style=3D"color:#660">::</span><span style=3D"color:#000">memcpy</span>=
<span style=3D"color:#660">(&</span><span style=3D"color:#000">b</span>=
<span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span=
style=3D"color:#660">&</span><span style=3D"color:#000">a</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">sizeof</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">a</span><span style=3D"color:#660">));</span><span style=3D=
"color:#000"><br> <br> std</span><span style=3D"c=
olor:#660">::</span><span style=3D"color:#000">memcpy</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">public_ptr</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> public_copy</span><span=
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">sizeof</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#000">public_copy</span><span style=3D"color:#660">));</span><sp=
an style=3D"color:#000"><br> std</span><span style=3D"color:#6=
60">::</span><span style=3D"color:#000">printf</span><span style=3D"color:#=
660">(</span><span style=3D"color:#080">"%g\n%p\n"</span><span style=3D"col=
or:#660">,</span><span style=3D"color:#000"> b</span><span style=3D"color:#=
660">.</span><span style=3D"color:#000">m_public</span><span style=3D"color=
:#660">,</span><span style=3D"color:#000"> public_ptr</span><span style=3D"=
color:#660">);</span><span style=3D"color:#000"><br> </span><s=
pan style=3D"color:#008">return</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#066">0</span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span sty=
le=3D"color:#000"><br></span></div></code></div><br>In order to support <sp=
an style=3D"font-family:courier new,monospace">m_public</span>'s offset not=
being constant, the implementation would have to magically handle the valu=
e of <span style=3D"font-family:courier new,monospace">public_ptr</span> ne=
eding to point to somewhere else after that second-to-last <span style=3D"f=
ont-family:courier new,monospace">memcpy</span>, even though the value of t=
he pointer is no different. Note that the implementation has to suppo=
rt this even though <span style=3D"font-family:courier new,monospace">publi=
c_ptr</span> could also be temporarily be obfuscated in a mangled <span sty=
le=3D"font-family:courier new,monospace">std::uintptr_t</span> somewhere.<b=
r><br>In short, this is kind of silly, and such an implementation should no=
t be a reason to not have <span style=3D"font-family:courier new,monospace"=
>offsetof</span> for all trivially-copyable types.<br><br>Melissa<br></div>=
</div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2075_1801994015.1411094992635--
.
Author: Myriachan <myriachan@gmail.com>
Date: Fri, 19 Sep 2014 01:12:21 -0700 (PDT)
Raw View
------=_Part_1890_1122726170.1411114342159
Content-Type: text/plain; charset=UTF-8
On Thursday, September 18, 2014 7:49:52 PM UTC-7, Matheus Izvekov wrote:
>
> On Thursday, September 18, 2014 8:51:37 PM UTC-3, Myriachan wrote:
>>
>>
>> From those two aspects of the definition of trivially copyable, you can
>> formally prove that the offset must be fixed from at least the time the
>> first memcpy to an unsigned char array is done.
>>
>
> Actually, on your proof that follows, you only try to address the first
> aspect, and not the second one. The point still remains that it is
> arbitrary to tie offsetof to is_trivially_copyable since they are unrelated
> concepts, even if it were the case that you could define offsetof for those
> in almost all circumstances.
> The current definition in the standard at least has the justification that
> it's trying to allow it only for C compatible types.
>
>
The point of my proof was to show that it was an arbitrary choice that
isn't required on technical grounds, based on the current (N3797)
definition of trivially-copyable types.
> Instead, I would suggest you try to start from scratch and try to define
> it in terms of more basic concepts.
>
Sure, if I were to *define* it, I *would* start from scratch =^-^= There
are other things that'd need to be fixed, though, such as the apparent
inconsistency I found in the definition of pointer arithmetic.
> I have three separate initial suggestions, and I will list them in order
> starting from safest and then on to most potentially dangerous.
>
> 1) Define offsetof as valid for all types which recursively don't contain
> classes with virtual inheritance.
> I think this would be the most broad category where all member
> offsets would be well defined, and they would be usable with both pointers
> to whole objects as well as to incomplete objects. This could possibly
> exclude taking the offset of member references.
>
>
My definitions would be as follows. By memcpy, I mean an operation that
results in sizeof(T) unsigned chars being assigned from one array/pointer
to another array/pointer, preserving order, but without regard to the
internal order of the individual byte copies themselves. Also, prior to
the memcpy operation's return, the destination unsigned chars may be
assigned any value, so long as they achieve their final correct state
before the return of memcpy. As usual, overlapping memcpy is undefined.
I'm just designing this to be as broad as possible, so as to cover the
ridiculous, within reason. I make a distinction between what is defined
and what is semantically correct. memcpy on a std::vector<int> to me is
defined, in the sense that because it has no virtual members or virtual
base classes, the contents of the class will make it from the source to the
destination. But it's semantically incorrect, because if you actually
tried to use the copied vector, it would blow up horribly, most likely with
a double-delete[].
Contrast this with memcpy of a class using virtual inheritance. The
structure of classes using virtual inheritance is so weird and strongly
implementation-specific that it's not going to work. Conceptually, virtual
inheritance cannot be tied to locations in a byte array in a
straightforward manner, particularly if you work with pointers to the base
classes separately, so this is completely undefined.
This is what I've thought of:
1. Split trivially-copyable up into two new looser forms in addition to
itself. trivially-copyable -> raw-memcpyable -> fixed-layout.
2. fixed-layout is the loosest, allowing anything but virtual inheritance.
2a. fixed-layout requires that members be stored in contiguous memory
(unsigned char[sizeof(T)]).
2b. No requirement that class management data like data for virtual
function dispatch be part of the contiguous block.
2c. offsetof is well-defined for all non-static data members, including
members of members, elements of member arrays, members of base class
subobjects, and recursively thereof. offsetof is conceptually defined for
reference types among such members, but is ill-formed for sanity reasons.
2d. reinterpret_cast<M *>(reinterpret_cast<unsigned char *>(&t) +
offsetof(T, m)) is well-defined and aliasing-compatible. Same for unions
with char/unsigned char arrays.
2e. fixed-layout classes would never change their sizes, their base
classes' "offsets", or their members' offsets, even when base class
subobjects, except when they are empty.
2f. Compilers can still physically coalesce members of identical
access-specifiers. Compilers can still reorder direct base classes as
desired (so long as construction order remains as written, of course).
3. raw-memcpyable means that memcpy of the type is well-defined as
memberwise scalar copying.
3a. Such classes can have copy constructors and such, so you can still run
into undefined behavior by doing something semantically incorrect like
memcpying a container class.
*Caveat programmator.*3b. raw-memcpyable classes are fixed-layout classes
with no virtual functions in themselves or any base classes...
3c. ...except that compilers may optionally support this if they want and
indicate it by #defining a macro to 1, say,
__cpp_all_fixed_layout_are_raw_memcpyable.
3d. memcpy of raw-memcpyable base class subobjects is defined only when the
class is nonempty and has no virtual functions (i.e. 3c optional feature
does not apply).
4. trivially-copyable is raw-memcpyable with no nontrivial copy/move
constructors/assignments/destructors.
4a. trivially-copyable is detected by the compiler for
std::is_trivially_copyable, etc. but in itself has no special features.
4b. [[trivially_copyable]] attribute marks a raw-memcpyable class as
trivially-copyable. Placing [[trivially-copyable]] on a non-raw-memcpyable
class is ill-formed. [[trivially-copyable]] may be placed on a class with
virtual functions #if __cpp_all_fixed_layout_are_raw_memcpyable.
4c. In other words, this concept still exists for its importance in
container programming.
5. standard-layout is a specialization of raw-memcpyable. It differs from
the current one in that it allows data members at multiple levels of the
hierarchy.
5a. All non-static data members within a standard-layout class must have
the same access-specifier. This is not required for base classes (but base
classes must obey this rule themselves, etc.).
5b. All direct base classes must have the same access-specifier. This is
not required for base classes (but base classes must obey this rule
themselves, etc.).
5c. A class is not standard-layout if at any point the rule about avoiding
address overlap between an empty base class subobject and a member triggers.
5d. Same rules about no virtual functions, offsets going in order, offset
of first non-static data member being 0, identical prefixes or entire
structures being layout-compatible.
5e. Direct base classes are laid out in memory in written order, unlike the
looser styles above, which are not held to this requirement.
5f. Algorithm for converting a standard-layout C++ structure into its C
form, in a sense, which would define its memory layout: Essentially, dump
out each non-static data member into a potentially-nested single C struct
in the C++ dynamic type's constructor order. Replace references and member
pointers with implementation-defined types that are fixed at compile time
for a given type. Apply equivalent attributes as needed, such as
_Alignas. Elided empty base classes are ignored.
5g. An empty standard-layout class that hasn't been elided due to empty
base class optimization is treated as if it has an anonymous private
non-static data member of type char.
6. fixed-layout empty derived class is a special case that I thought of in
one of the threads here. It's a fixed-layout class with no non-static data
members of its own that derives from a single base class.
6a. Such a derived class can only have virtual functions that override
those in the base class - it cannot add virtual functions of its own. This
is to guarantee that a vtable pointer is not added to the class.
6b. The result is that sizeof(Derived) == sizeof(Base).
6c. Unlike the typical rules, this feature is designed to allow accessing a
Derived array using a Base * - normally such pointer arithmetic on
polymorphic types is Bad News (tm) but here it'd be valid.
6d. Accessing a Base array using a Derived * would also be allowed, but you
better be careful with that one, since those objects weren't created with
the Derived constructor. Again, *caveat programmator*...
6c. raw-memcpyable, trivially-copyable, and standard-layout classes can
also be of this kind - this is not an exclusive category.
Crazy enough? =/
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1890_1122726170.1411114342159
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, September 18, 2014 7:49:52 PM UTC-7, Matheus =
Izvekov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
>On Thursday, September 18, 2014 8:51:37 PM UTC-3, Myriachan wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br>From those two as=
pects of the definition of trivially copyable, you can formally prove that =
the offset must be fixed from at least the time the first <span style=3D"fo=
nt-family:courier new,monospace">memcpy</span> to an <span style=3D"font-fa=
mily:courier new,monospace">unsigned char</span> array is done.</div></div>=
</blockquote><div><br>Actually, on your proof that follows, you only try to=
address the first aspect, and not the second one. The point still remains =
that it is arbitrary to tie offsetof to is_trivially_copyable since they ar=
e unrelated concepts, even if it were the case that you could define offset=
of for those in almost all circumstances.<br>The current definition in the =
standard at least has the justification that it's trying to allow it only f=
or C compatible types.<br><br></div></div></blockquote><div><br>The point o=
f my proof was to show that it was an arbitrary choice that isn't required =
on technical grounds, based on the current (N3797) definition of trivially-=
copyable types.<br> </div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div>Instead, I would suggest you try to start from scrat=
ch and try to define it in terms of more basic concepts. <br></div></div></=
blockquote><div><br>Sure, if I were to <i>define</i> it, I <i>would</i> sta=
rt from scratch =3D^-^=3D There are other things that'd need to be fi=
xed, though, such as the apparent inconsistency I found in the definition o=
f pointer arithmetic.<br> </div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div>I have three separate initial suggestions, and=
I will list them in order starting from safest and then on to most potenti=
ally dangerous. <br></div></div></blockquote><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><div><br>1) Define offsetof as valid for al=
l types which recursively don't contain classes with virtual inheritance.<b=
r> I think this would be the most broad category wh=
ere all member offsets would be well defined, and they would be usable with=
both pointers to whole objects as well as to incomplete objects. This coul=
d possibly exclude taking the offset of member references.<br><br></div></d=
iv></blockquote><div><br>My definitions would be as follows. By <span=
style=3D"font-family: courier new,monospace;">memcpy</span>, I mean an ope=
ration that results in <span style=3D"font-family: courier new,monospace;">=
sizeof(T)</span> <span style=3D"font-family: courier new,monospace;">unsign=
ed char</span>s being assigned from one array/pointer to another array/poin=
ter, preserving order, but without regard to the internal order of the indi=
vidual byte copies themselves. Also, prior to the <span style=3D"font=
-family: courier new,monospace;">memcpy</span> operation's return, the dest=
ination unsigned chars may be assigned any value, so long as they achieve t=
heir final correct state before the return of <span style=3D"font-family: c=
ourier new,monospace;">memcpy</span>. As usual, overlapping <span sty=
le=3D"font-family: courier new,monospace;">memcpy</span> is undefined.<br><=
br>I'm just designing this to be as broad as possible, so as to cover the r=
idiculous, within reason. I make a distinction between what is define=
d and what is semantically correct. <span style=3D"font-family: couri=
er new,monospace;">memcpy</span> on a <span style=3D"font-family: courier n=
ew,monospace;">std::vector<int></span> to me is defined, in the sense=
that because it has no virtual members or virtual base classes, the conten=
ts of the class will make it from the source to the destination. But =
it's semantically incorrect, because if you actually tried to use the copie=
d vector, it would blow up horribly, most likely with a double-<span style=
=3D"font-family: courier new,monospace;">delete[]</span>.<br><br>Contrast t=
his with <span style=3D"font-family: courier new,monospace;">memcpy</span> =
of a class using virtual inheritance. The structure of classes using =
virtual inheritance is so weird and strongly implementation-specific that i=
t's not going to work. Conceptually, virtual inheritance cannot be ti=
ed to locations in a byte array in a straightforward manner, particularly i=
f you work with pointers to the base classes separately, so this is complet=
ely undefined.<br><br>This is what I've thought of:<br><br>1. Split trivial=
ly-copyable up into two new looser forms in addition to itself. trivi=
ally-copyable -> raw-memcpyable -> fixed-layout.<br><br>2. fixed-layo=
ut is the loosest, allowing anything but virtual inheritance.<br>2a. fixed-=
layout requires that members be stored in contiguous memory (unsigned char[=
sizeof(T)]).<br>2b. No requirement that class management data like data for=
virtual function dispatch be part of the contiguous block.<br>2c. offsetof=
is well-defined for all non-static data members, including members of memb=
ers, elements of member arrays, members of base class subobjects, and recur=
sively thereof. offsetof is conceptually defined for reference types =
among such members, but is ill-formed for sanity reasons.<br>2d. reinterpre=
t_cast<M *>(reinterpret_cast<unsigned char *>(&t) + offseto=
f(T, m)) is well-defined and aliasing-compatible. Same for unions wit=
h char/unsigned char arrays.<br>2e. fixed-layout classes would never change=
their sizes, their base classes' "offsets", or their members' offsets, eve=
n when base class subobjects, except when they are empty.<br>2f. Compilers =
can still physically coalesce members of identical access-specifiers. =
Compilers can still reorder direct base classes as desired (so long as con=
struction order remains as written, of course).<br><br>3. raw-memcpyable me=
ans that memcpy of the type is well-defined as memberwise scalar copying.<b=
r>3a. Such classes can have copy constructors and such, so you can still ru=
n into undefined behavior by doing something semantically incorrect like me=
mcpying a container class. <i>Caveat programmator.<br></i>3b. raw-mem=
cpyable classes are fixed-layout classes with no virtual functions in thems=
elves or any base classes...<br>3c. ...except that compilers may optionally=
support this if they want and indicate it by #defining a macro to 1, say, =
__cpp_all_fixed_layout_are_raw_memcpyable.<br>3d. memcpy of raw-memcpyable =
base class subobjects is defined only when the class is nonempty and has no=
virtual functions (i.e. 3c optional feature does not apply).<br><br>4. tri=
vially-copyable is raw-memcpyable with no nontrivial copy/move constructors=
/assignments/destructors.<br>4a. trivially-copyable is detected by the comp=
iler for std::is_trivially_copyable, etc. but in itself has no special feat=
ures.<br>4b. [[trivially_copyable]] attribute marks a raw-memcpyable class =
as trivially-copyable. Placing [[trivially-copyable]] on a non-raw-me=
mcpyable class is ill-formed. [[trivially-copyable]] may be placed on=
a class with virtual functions #if __cpp_all_fixed_layout_are_raw_memcpyab=
le.<br>4c. In other words, this concept still exists for its importance in =
container programming.<br><br>5. standard-layout is a specialization of raw=
-memcpyable. It differs from the current one in that it allows data m=
embers at multiple levels of the hierarchy.<br>5a. All non-static data memb=
ers within a standard-layout class must have the same access-specifier.&nbs=
p; This is not required for base classes (but base classes must obey this r=
ule themselves, etc.).<br>5b. All direct base classes must have the same ac=
cess-specifier. This is not required for base classes (but base class=
es must obey this rule themselves, etc.).<br>5c. A class is not standard-la=
yout if at any point the rule about avoiding address overlap between an emp=
ty base class subobject and a member triggers.<br>5d. Same rules about no v=
irtual functions, offsets going in order, offset of first non-static data m=
ember being 0, identical prefixes or entire structures being layout-compati=
ble.<br>5e. Direct base classes are laid out in memory in written order, un=
like the looser styles above, which are not held to this requirement.<br>5f=
.. Algorithm for converting a standard-layout C++ structure into its C form,=
in a sense, which would define its memory layout: Essentially, dump out ea=
ch non-static data member into a potentially-nested single C struct in the =
C++ dynamic type's constructor order. Replace references and member p=
ointers with implementation-defined types that are fixed at compile time fo=
r a given type. Apply equivalent attributes as needed, such as _Align=
as. Elided empty base classes are ignored.<br>5g. An empty standard-l=
ayout class that hasn't been elided due to empty base class optimization is=
treated as if it has an anonymous private non-static data member of type c=
har.<br><br>6. fixed-layout empty derived class is a special case that I th=
ought of in one of the threads here. It's a fixed-layout class with n=
o non-static data members of its own that derives from a single base class.=
<br>6a. Such a derived class can only have virtual functions that override =
those in the base class - it cannot add virtual functions of its own. =
This is to guarantee that a vtable pointer is not added to the class.<br>6=
b. The result is that sizeof(Derived) =3D=3D sizeof(Base).<br>6c. Unlike th=
e typical rules, this feature is designed to allow accessing a Derived arra=
y using a Base * - normally such pointer arithmetic on polymorphic types is=
Bad News (tm) but here it'd be valid.<br>6d. Accessing a Base array using =
a Derived * would also be allowed, but you better be careful with that one,=
since those objects weren't created with the Derived constructor. Ag=
ain, <i>caveat programmator</i>...<br>6c. raw-memcpyable, trivially-copyabl=
e, and standard-layout classes can also be of this kind - this is not an ex=
clusive category.<br><br><br>Crazy enough? =3D/<br><br>Melissa<br></div></d=
iv>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1890_1122726170.1411114342159--
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Fri, 19 Sep 2014 06:12:33 -0700 (PDT)
Raw View
------=_Part_2353_987329338.1411132353774
Content-Type: text/plain; charset=UTF-8
On Friday, September 19, 2014 5:12:22 AM UTC-3, Myriachan wrote:
>
> This is what I've thought of:
>
> 1. Split trivially-copyable up into two new looser forms in addition to
> itself. trivially-copyable -> raw-memcpyable -> fixed-layout.
>
> 2. fixed-layout is the loosest, allowing anything but virtual inheritance.
> 2a. fixed-layout requires that members be stored in contiguous memory
> (unsigned char[sizeof(T)]).
>
Well, if you are going this far, why not take it one step further: Every
complete object shall occupy contiguous bytes of storage.
Though this would not mean a complete object would necessarily be
memcpyable, ie implementations would still be allowed
to store pointers to internal storage in order to implement virtual
inheritance.
This also would not mean that every subobject should necessarily occupy
contiguous bytes of memory, ie a subobject could be laid non-contiguously
with one of it's virtual bases.
I'd be surprised if any implementations would have trouble with this.
3. raw-memcpyable means that memcpy of the type is well-defined as
> memberwise scalar copying.
> 3a. Such classes can have copy constructors and such, so you can still run
> into undefined behavior by doing something semantically incorrect like
> memcpying a container class.
> *Caveat programmator.*3b. raw-memcpyable classes are fixed-layout classes
> with no virtual functions in themselves or any base classes...
>
3c. ...except that compilers may optionally support this if they want and
> indicate it by #defining a macro to 1, say,
> __cpp_all_fixed_layout_are_raw_memcpyable.
>
3d. memcpy of raw-memcpyable base class subobjects is defined only when the
> class is nonempty and has no virtual functions (i.e. 3c optional feature
> does not apply).
>
>
How about a trait named something like is_memcpy_defined<T>, which when
true, means that it is well formed to memcpy a complete object of type T.
With the same caveat that this does not necessarily mean that the copy
represents the same value as the original.
This trait would be required to be true for all types which don't
recursively contain members / sub-objects with virtual inheritance /
virtual methods, and
it would be implementation defined if it would be true for types which do
contain those.
> 4. trivially-copyable is raw-memcpyable with no nontrivial copy/move
> constructors/assignments/destructors.
>
I think here you meant to say "trivially-copyable is raw-memcpyable with no
nontrivial copy/move constructors/assignments and a trivial destructor."
> 4a. trivially-copyable is detected by the compiler for
> std::is_trivially_copyable, etc. but in itself has no special features.
> 4b. [[trivially_copyable]] attribute marks a raw-memcpyable class as
> trivially-copyable. Placing [[trivially-copyable]] on a non-raw-memcpyable
> class is ill-formed. [[trivially-copyable]] may be placed on a class with
> virtual functions #if __cpp_all_fixed_layout_are_raw_memcpyable.
> 4c. In other words, this concept still exists for its importance in
> container programming.
>
>
Attributes are problematic for this, I mentioned several times that it
would take some convincing of the committee in order for them to accept
attributes which change the language semantics.
Specializing a template in the std namespace could be done instead.
> 5. standard-layout is a specialization of raw-memcpyable. It differs from
> the current one in that it allows data members at multiple levels of the
> hierarchy.
>
I completely missed the point of this section, or what it even means for it
to be a specialization of raw-memcpyable.
I don't see why standard-layout would need to be changed.
> 6. fixed-layout empty derived class is a special case that I thought of in
> one of the threads here. It's a fixed-layout class with no non-static data
> members of its own that derives from a single base class.
>
Also missed the point of this one.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2353_987329338.1411132353774
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, September 19, 2014 5:12:22 AM UTC-3, Myriachan =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Th=
is is what I've thought of:<br><br>1. Split trivially-copyable up into two =
new looser forms in addition to itself. trivially-copyable -> raw-=
memcpyable -> fixed-layout.<br><br>2. fixed-layout is the loosest, allow=
ing anything but virtual inheritance.<br>2a. fixed-layout requires that mem=
bers be stored in contiguous memory (unsigned char[sizeof(T)]).<br></div></=
div></blockquote><div><br>Well, if you are going this far, why not take it =
one step further: Every complete object shall occupy contiguous bytes of st=
orage.<br>Though this would not mean a complete object would necessarily be=
memcpyable, ie implementations would still be allowed<br>to store pointers=
to internal storage in order to implement virtual inheritance.<br><br>This=
also would not mean that every subobject should necessarily occupy contigu=
ous bytes of memory, ie a subobject could be laid non-contiguously with one=
of it's virtual bases.<br><br>I'd be surprised if any implementations woul=
d have trouble with this.<br><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div>3. raw-memcpyable means that memcpy of the t=
ype is well-defined as memberwise scalar copying.<br>3a. Such classes can h=
ave copy constructors and such, so you can still run into undefined behavio=
r by doing something semantically incorrect like memcpying a container clas=
s. <i>Caveat programmator.<br></i>3b. raw-memcpyable classes are fixe=
d-layout classes with no virtual functions in themselves or any base classe=
s... <br></div></div></blockquote><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div>3c. ...except that compilers may optionally sup=
port this if they want and indicate it by #defining a macro to 1, say, __cp=
p_all_fixed_layout_are_<wbr>raw_memcpyable. </div></div></blockquote><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>3d. memcpy of =
raw-memcpyable base class subobjects is defined only when the class is none=
mpty and has no virtual functions (i.e. 3c optional feature does not apply)=
..<br><br></div></div></blockquote><div><br>How about a trait named somethin=
g like is_memcpy_defined<T>, which when true, means that it is well f=
ormed to memcpy a complete object of type T.<br>With the same caveat that t=
his does not necessarily mean that the copy represents the same value as th=
e original.<br>This trait would be required to be true for all types which =
don't recursively contain members / sub-objects with virtual inheritance / =
virtual methods, and<br>it would be implementation defined if it would be t=
rue for types which do contain those.<br> </div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div>4. trivially-copyable is raw-m=
emcpyable with no nontrivial copy/move constructors/assignments/<wbr>destru=
ctors.<br></div></div></blockquote><div><br>I think here you meant to say "=
trivially-copyable is raw-memcpyable with no nontrivial copy/move construct=
ors/assignments and a trivial destructor."<br> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>4a. trivially-copyable is=
detected by the compiler for std::is_trivially_copyable, etc. but in itsel=
f has no special features.<br>4b. [[trivially_copyable]] attribute marks a =
raw-memcpyable class as trivially-copyable. Placing [[trivially-copya=
ble]] on a non-raw-memcpyable class is ill-formed. [[trivially-copyab=
le]] may be placed on a class with virtual functions #if __cpp_all_fixed_la=
yout_are_<wbr>raw_memcpyable.<br>4c. In other words, this concept still exi=
sts for its importance in container programming.<br><br></div></div></block=
quote><div><br>Attributes are problematic for this,<i> </i>I mentioned seve=
ral times that it would take some convincing of the committee in order for =
them to accept attributes which change the language semantics.<br>Specializ=
ing a template in the std namespace could be done instead.<br> </div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>5. standa=
rd-layout is a specialization of raw-memcpyable. It differs from the =
current one in that it allows data members at multiple levels of the hierar=
chy.<br></div></div></blockquote><div><br>I completely missed the point of =
this section, or what it even means for it to be a specialization of raw-me=
mcpyable.<br>I don't see why standard-layout would need to be changed.<br>&=
nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><d=
iv>6. fixed-layout empty derived class is a special case that I thought of =
in one of the threads here. It's a fixed-layout class with no non-sta=
tic data members of its own that derives from a single base class.<br></div=
></div></blockquote><div><br>Also missed the point of this one.<br></div></=
div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2353_987329338.1411132353774--
.
Author: Myriachan <myriachan@gmail.com>
Date: Fri, 19 Sep 2014 21:33:41 -0700 (PDT)
Raw View
------=_Part_4672_1260835237.1411187621876
Content-Type: text/plain; charset=UTF-8
On Friday, September 19, 2014 6:12:33 AM UTC-7, Matheus Izvekov wrote:
>
> On Friday, September 19, 2014 5:12:22 AM UTC-3, Myriachan wrote:
>>
>> This is what I've thought of:
>>
>> 1. Split trivially-copyable up into two new looser forms in addition to
>> itself. trivially-copyable -> raw-memcpyable -> fixed-layout.
>>
>> 2. fixed-layout is the loosest, allowing anything but virtual inheritance.
>> 2a. fixed-layout requires that members be stored in contiguous memory
>> (unsigned char[sizeof(T)]).
>>
>
> Well, if you are going this far, why not take it one step further: Every
> complete object shall occupy contiguous bytes of storage.
> Though this would not mean a complete object would necessarily be
> memcpyable, ie implementations would still be allowed
> to store pointers to internal storage in order to implement virtual
> inheritance.
>
> This also would not mean that every subobject should necessarily occupy
> contiguous bytes of memory, ie a subobject could be laid non-contiguously
> with one of it's virtual bases.
>
> I'd be surprised if any implementations would have trouble with this.
>
OK, I like this design more than mine. =^-^=
What about a requirement that all non-empty subobjects that do not have any
virtual base classes anywhere above themselves in the hierarchy (it's OK if
*they* are a virtual base) are in contiguous bytes of memory and have a
fixed layout? I mean, so that you could do this without
implementation-defined / undefined behavior:
#include <cerrno>
#include <cstdio>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
typedef struct stat StatAlias; // obviously standard-layout
struct Left : virtual public StatAlias { int left; };
struct Right : virtual public StatAlias { int right; };
struct Diamond : public Left, public Right { int diamond; };
int main(int, const char *const *argv)
{
Diamond diamond;
errno = 0;
if (argv[0] && (stat(argv[0], &diamond) == 0)) {
std::printf("%zu\n", static_cast<std::size_t>(diamond.st_size));
} else {
perror(argv[0]);
}
return 0;
}
> 3. raw-memcpyable means that memcpy of the type is well-defined as
>> memberwise scalar copying.
>> 3a. Such classes can have copy constructors and such, so you can still
>> run into undefined behavior by doing something semantically incorrect like
>> memcpying a container class.
>> *Caveat programmator.*3b. raw-memcpyable classes are fixed-layout
>> classes with no virtual functions in themselves or any base classes...
>>
> 3c. ...except that compilers may optionally support this if they want and
>> indicate it by #defining a macro to 1, say,
>> __cpp_all_fixed_layout_are_raw_memcpyable.
>>
> 3d. memcpy of raw-memcpyable base class subobjects is defined only when
>> the class is nonempty and has no virtual functions (i.e. 3c optional
>> feature does not apply).
>>
>>
> How about a trait named something like is_memcpy_defined<T>, which when
> true, means that it is well formed to memcpy a complete object of type T.
> With the same caveat that this does not necessarily mean that the copy
> represents the same value as the original.
> This trait would be required to be true for all types which don't
> recursively contain members / sub-objects with virtual inheritance /
> virtual methods, and
> it would be implementation defined if it would be true for types which do
> contain those.
>
Yes, this works. Should there also be a secondary trait class that
specifically means ones that are in the required category as opposed to
ones that are just optionally supported by the implementation?
>
>
>> 4. trivially-copyable is raw-memcpyable with no nontrivial copy/move
>> constructors/assignments/destructors.
>>
>
> I think here you meant to say "trivially-copyable is raw-memcpyable with
> no nontrivial copy/move constructors/assignments and a trivial destructor."
>
Is there a difference, other than that there can only be one destructor?
>
>
>> 4a. trivially-copyable is detected by the compiler for
>> std::is_trivially_copyable, etc. but in itself has no special features.
>> 4b. [[trivially_copyable]] attribute marks a raw-memcpyable class as
>> trivially-copyable. Placing [[trivially-copyable]] on a non-raw-memcpyable
>> class is ill-formed. [[trivially-copyable]] may be placed on a class with
>> virtual functions #if __cpp_all_fixed_layout_are_raw_memcpyable.
>> 4c. In other words, this concept still exists for its importance in
>> container programming.
>>
>>
> Attributes are problematic for this, I mentioned several times that it
> would take some convincing of the committee in order for them to accept
> attributes which change the language semantics.
> Specializing a template in the std namespace could be done instead.
>
Specializing std::is_trivially_copyable<> would be fine, if the standard
containers would be updated to have to obey it. Current implementations
often directly use the compiler intrinsics or other tricks.
There is already a case in current C++ where attributes change language
semantics:
constexpr int square(int x) { return x * x; }
[[noreturn]] constexpr void func1() { }
constexpr void func2() { }
int main()
{
// Ill-formed by [dcl.attr.noreturn]/2 and [expr.const]/2.5
return std::integral_constant<int, (func1(), square(5))>::value;
// Well-formed
return std::integral_constant<int, (func2(), square(5))>::value;
}
>
>
>> 5. standard-layout is a specialization of raw-memcpyable. It differs
>> from the current one in that it allows data members at multiple levels of
>> the hierarchy.
>>
>
> I completely missed the point of this section, or what it even means for
> it to be a specialization of raw-memcpyable.
> I don't see why standard-layout would need to be changed.
>
By "specialization", I just meant that the set of standard-layout classes
is a subset of the set of raw-memcpyable classes. "Specialization" is a
poor choice of word for me to use in a discussion of C++ when it's not
talking about templates, sorry...
My changes to standard-layout essentially just allow non-static data
members at multiple levels of the hierarchy. This just makes it possible
to implement some data structures more easily. A simple example is sockaddr
/sockaddr_in/sockaddr_in6/sockaddr_un. Rather than having to go the C way
of reinterpret_casting everywhere (or C-style casting), you can use C++
inheritance, and still be able to pass the data to C when required.
>
>
>> 6. fixed-layout empty derived class is a special case that I thought of
>> in one of the threads here. It's a fixed-layout class with no non-static
>> data members of its own that derives from a single base class.
>>
>
> Also missed the point of this one.
>
The current C++11/C++14 definition of standard-layout permits deriving from
standard-layout classes and remaining standard-layout, so long as you don't
add any non-static data members or break the standard-layout rules. #6 is
designed to extend that concept to a broader set of types. The
standard-layout inheritance rule combined with other aspects of the
Standard, such as *layout-compatible*, allow you to get away with things
like using pointers of different class types than what was originally
constructed. You can have a pointer to a C structure, static_cast it to
your derived class, and call member functions on it. So long as you don't
care about the constructors and destructors, this will work, even if the
object was originally constructed/initialized as the C structure.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4672_1260835237.1411187621876
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, September 19, 2014 6:12:33 AM UTC-7, Matheus Iz=
vekov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">O=
n Friday, September 19, 2014 5:12:22 AM UTC-3, Myriachan wrote:<blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>This is what I've thought=
of:<br><br>1. Split trivially-copyable up into two new looser forms in add=
ition to itself. trivially-copyable -> raw-memcpyable -> fixed-=
layout.<br><br>2. fixed-layout is the loosest, allowing anything but virtua=
l inheritance.<br>2a. fixed-layout requires that members be stored in conti=
guous memory (unsigned char[sizeof(T)]).<br></div></div></blockquote><div><=
br>Well, if you are going this far, why not take it one step further: Every=
complete object shall occupy contiguous bytes of storage.<br>Though this w=
ould not mean a complete object would necessarily be memcpyable, ie impleme=
ntations would still be allowed<br>to store pointers to internal storage in=
order to implement virtual inheritance.<br><br>This also would not mean th=
at every subobject should necessarily occupy contiguous bytes of memory, ie=
a subobject could be laid non-contiguously with one of it's virtual bases.=
<br><br>I'd be surprised if any implementations would have trouble with thi=
s.<br></div></div></blockquote><div><br>OK, I like this design more than mi=
ne. =3D^-^=3D<br><br>What about a requirement that all non-empty subobjects=
that do not have any virtual base classes anywhere above themselves in the=
hierarchy (it's OK if <i>they</i> are a virtual base) are in contiguous by=
tes of memory and have a fixed layout? I mean, so that you could do t=
his without implementation-defined / undefined behavior:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
style=3D"color: #800;" class=3D"styled-by-prettify">#include</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #080;" class=3D"styled-by-prettify"><cerrno></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #800;" class=3D"styled-by-prettify">#include</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #080;"=
class=3D"styled-by-prettify"><cstdio></span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #800;" c=
lass=3D"styled-by-prettify">#include</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #080;" class=3D"sty=
led-by-prettify"><unistd.h></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">#include</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-pre=
ttify"><sys/stat.h></span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">#include</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">&l=
t;sys/types.h></span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">typedef</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> stat </spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">StatAlias</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// obviously standard-layout=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Left</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">virtual</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">public</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">StatAlia=
s</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> left</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">struc=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #606;" class=3D"styled-by-prettify">Right</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">virtual</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">public</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">StatAlias</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> right</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Diamond=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">public</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Left</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>public</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">Right</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> diamond</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">int<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> main</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">char</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">argv</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br> </span><span style=3D"color: #606;" class=3D"sty=
led-by-prettify">Diamond</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> diamond</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br> errno </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify"=
>0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">argv</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">[</span><span style=3D"color: #066;" clas=
s=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">]</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&a=
mp;&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">stat</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">argv</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">[</span><span style=3D"color: #066;" clas=
s=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">],</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">diamon=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
066;" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">))</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br> std</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">printf</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #080;" class=3D"styled-by-pretti=
fy">"%zu\n"</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">static_cast</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">size_t</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">>(</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">diamond</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">st_size</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">el=
se</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br> &=
nbsp; perror</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">argv</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><span=
style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">]);</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
66;" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span></div></code></div><br><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><div><br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>3. raw-memcpyable means that memcpy of th=
e type is well-defined as memberwise scalar copying.<br>3a. Such classes ca=
n have copy constructors and such, so you can still run into undefined beha=
vior by doing something semantically incorrect like memcpying a container c=
lass. <i>Caveat programmator.<br></i>3b. raw-memcpyable classes are f=
ixed-layout classes with no virtual functions in themselves or any base cla=
sses... <br></div></div></blockquote><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div>3c. ...except that compilers may optionally support=
this if they want and indicate it by #defining a macro to 1, say, __cpp_al=
l_fixed_layout_are_<wbr>raw_memcpyable. </div></div></blockquote><blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>3d. memcpy of raw-memcp=
yable base class subobjects is defined only when the class is nonempty and =
has no virtual functions (i.e. 3c optional feature does not apply).<br><br>=
</div></div></blockquote><div><br>How about a trait named something like is=
_memcpy_defined<T>, which when true, means that it is well formed to =
memcpy a complete object of type T.<br>With the same caveat that this does =
not necessarily mean that the copy represents the same value as the origina=
l.<br>This trait would be required to be true for all types which don't rec=
ursively contain members / sub-objects with virtual inheritance / virtual m=
ethods, and<br>it would be implementation defined if it would be true for t=
ypes which do contain those.<br></div></div></blockquote><div><br>Yes, this=
works. Should there also be a secondary trait class that specificall=
y means ones that are in the required category as opposed to ones that are =
just optionally supported by the implementation?<br> </div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> </div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>4. trivially-copyabl=
e is raw-memcpyable with no nontrivial copy/move constructors/assignments/<=
wbr>destructors.<br></div></div></blockquote><div><br>I think here you mean=
t to say "trivially-copyable is raw-memcpyable with no nontrivial copy/move=
constructors/assignments and a trivial destructor."<br></div></div></block=
quote><div><br>Is there a difference, other than that there can only be one=
destructor?<br> </div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><div> </div><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div>4a. trivially-copyable is detected by the compiler for s=
td::is_trivially_copyable, etc. but in itself has no special features.<br>4=
b. [[trivially_copyable]] attribute marks a raw-memcpyable class as trivial=
ly-copyable. Placing [[trivially-copyable]] on a non-raw-memcpyable c=
lass is ill-formed. [[trivially-copyable]] may be placed on a class w=
ith virtual functions #if __cpp_all_fixed_layout_are_<wbr>raw_memcpyable.<b=
r>4c. In other words, this concept still exists for its importance in conta=
iner programming.<br><br></div></div></blockquote><div><br>Attributes are p=
roblematic for this,<i> </i>I mentioned several times that it would take so=
me convincing of the committee in order for them to accept attributes which=
change the language semantics.<br>Specializing a template in the std names=
pace could be done instead.<br></div></div></blockquote><div><br>Specializi=
ng <span style=3D"font-family: courier new,monospace;">std::is_trivially_co=
pyable<></span> would be fine, if the standard containers would be up=
dated to have to obey it. Current implementations often directly use =
the compiler intrinsics or other tricks.<br><br>There is already a case in =
current C++ where attributes change language semantics:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
style=3D"color: #008;" class=3D"styled-by-prettify">constexpr</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> square</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> x</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> x </span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> x</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">[[</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">noreturn</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">]]</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> func1</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> func2</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> main</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// Ill-formed by [dcl.attr.noreturn]/2 and [expr.co=
nst]/2.5</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">integral_con=
stant</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">func1</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(),</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> square</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #066;" class=3D"styled-by-pret=
tify">5</span><span style=3D"color: #660;" class=3D"styled-by-prettify">))&=
gt;::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">value=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br> <=
/span><span style=3D"color: #800;" class=3D"styled-by-prettify">// Well-for=
med</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nb=
sp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">integral_constant=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">func2</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(),</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> square</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">(</span><span style=3D"color: #066;" class=3D"styled-by-prettify"=
>5</span><span style=3D"color: #660;" class=3D"styled-by-prettify">))>::=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">value</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></div><=
br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><div> </div><blockquote class=3D"gmail_quote" style=3D"margin:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div>5. standard-layout is a specialization of raw-memcpyable. It di=
ffers from the current one in that it allows data members at multiple level=
s of the hierarchy.<br></div></div></blockquote><div><br>I completely misse=
d the point of this section, or what it even means for it to be a specializ=
ation of raw-memcpyable.<br>I don't see why standard-layout would need to b=
e changed.<br></div></div></blockquote><div><br>By "specialization", I just=
meant that the set of standard-layout classes is a subset of the set of ra=
w-memcpyable classes. "Specialization" is a poor choice of word for m=
e to use in a discussion of C++ when it's not talking about templates, sorr=
y...<br><br>My changes to standard-layout essentially just allow non-static=
data members at multiple levels of the hierarchy. This just makes it=
possible to implement some data structures more easily. A simple exa=
mple is <span style=3D"font-family: courier new,monospace;">sockaddr</span>=
/<span style=3D"font-family: courier new,monospace;">sockaddr_in</span>/<sp=
an style=3D"font-family: courier new,monospace;">sockaddr_in6</span>/<span =
style=3D"font-family: courier new,monospace;">sockaddr_un</span>. Rat=
her than having to go the C way of <span style=3D"font-family: courier new,=
monospace;">reinterpret_cast</span>ing everywhere (or C-style casting), you=
can use C++ inheritance, and still be able to pass the data to C when requ=
ired.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div> </div><blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>6. fixed-layout empty derived class is a special case that I =
thought of in one of the threads here. It's a fixed-layout class with=
no non-static data members of its own that derives from a single base clas=
s.<br></div></div></blockquote><div><br>Also missed the point of this one.<=
br></div></div></blockquote><div><br>The current C++11/C++14 definition of =
standard-layout permits deriving from standard-layout classes and remaining=
standard-layout, so long as you don't add any non-static data members or b=
reak the standard-layout rules. #6 is designed to extend that concept=
to a broader set of types. The standard-layout inheritance rule comb=
ined with other aspects of the Standard, such as <i>layout-compatible</i>, =
allow you to get away with things like using pointers of different class ty=
pes than what was originally constructed. You can have a pointer to a=
C structure, <span style=3D"font-family: courier new,monospace;">static_ca=
st</span> it to your derived class, and call member functions on it. =
So long as you don't care about the constructors and destructors, this will=
work, even if the object was originally constructed/initialized as the C s=
tructure.<br><br>Melissa<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4672_1260835237.1411187621876--
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Fri, 19 Sep 2014 23:01:36 -0700 (PDT)
Raw View
------=_Part_2944_444535108.1411192897040
Content-Type: text/plain; charset=UTF-8
On Saturday, September 20, 2014 1:33:42 AM UTC-3, Myriachan wrote:
>
> OK, I like this design more than mine. =^-^=
>
> What about a requirement that all non-empty subobjects that do not have
> any virtual base classes anywhere above themselves in the hierarchy (it's
> OK if *they* are a virtual base) are in contiguous bytes of memory and
> have a fixed layout? I mean, so that you could do this without
> implementation-defined / undefined behavior:
>
Yeah that is right, I missed specifying that :)
Yes, this works. Should there also be a secondary trait class that
> specifically means ones that are in the required category as opposed to
> ones that are just optionally supported by the implementation?
>
I don't have any specific objection other than because I don't see why that
would be important. In what circumstances would that distinction be useful
to the programmer?
> Is there a difference, other than that there can only be one destructor?
>
Well, if you look at the current wording in the draft, it goes out of the
way to specifically state it like I did, and I presumed you are not trying
to change anything here.
Note though that as I discussed in the other thread, I would be interested
in changing the specification for this trait.
> Specializing std::is_trivially_copyable<> would be fine, if the standard
> containers would be updated to have to obey it. Current implementations
> often directly use the compiler intrinsics or other tricks.
>
As I argued in the other thread, I think it would be a bad idea to let the
user override this when is_memcpy_defined is false.
Specifically, if is_memcpy_defined<T>{} is false, then
is_trivially_copyable<T>{} should be false independent of any user
specializations.
To make this work, it would be required that users don't specialize
is_trivially_copyable.
> There is already a case in current C++ where attributes change language
> semantics:
>
I think this does not change the language semantics as is understood by the
committee members.
For it to happen, it would require that the attribute have an observable
effect on the program beyond
changing execution timing. For example, allowing an attribute to change the
value of a trait, the size
of an object, overload resolution, etc.
Making the program ill-formed in case the attribute is misused is not
really changing the semantics.
> My changes to standard-layout essentially just allow non-static data
> members at multiple levels of the hierarchy. This just makes it possible
> to implement some data structures more easily. A simple example is
> sockaddr/sockaddr_in/sockaddr_in6/sockaddr_un. Rather than having to go
> the C way of reinterpret_casting everywhere (or C-style casting), you can
> use C++ inheritance, and still be able to pass the data to C when required.
>
I see, can you provide one of your kitty examples here? Just to make things
more clear.
> The current C++11/C++14 definition of standard-layout permits deriving
> from standard-layout classes and remaining standard-layout, so long as you
> don't add any non-static data members or break the standard-layout rules.
> #6 is designed to extend that concept to a broader set of types. The
> standard-layout inheritance rule combined with other aspects of the
> Standard, such as *layout-compatible*, allow you to get away with things
> like using pointers of different class types than what was originally
> constructed. You can have a pointer to a C structure, static_cast it to
> your derived class, and call member functions on it. So long as you don't
> care about the constructors and destructors, this will work, even if the
> object was originally constructed/initialized as the C structure.
>
I see, well presumably you want this so you can create wrappers for C
libraries, with no overhead, and still be able to freely mix the C style
functions with the C++ style objects?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2944_444535108.1411192897040
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, September 20, 2014 1:33:42 AM UTC-3, Myriacha=
n wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
OK, I like this design more than mine. =3D^-^=3D<br><br>What about a requir=
ement that all non-empty subobjects that do not have any virtual base class=
es anywhere above themselves in the hierarchy (it's OK if <i>they</i> are a=
virtual base) are in contiguous bytes of memory and have a fixed layout?&n=
bsp; I mean, so that you could do this without implementation-defined / und=
efined behavior:<br></div></div></blockquote><div><br>Yeah that is right, I=
missed specifying that :)<br><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div>Yes, this works. Should there also be=
a secondary trait class that specifically means ones that are in the requi=
red category as opposed to ones that are just optionally supported by the i=
mplementation?<br></div></div></blockquote><div><br>I don't have any specif=
ic objection other than because I don't see why that would be important. In=
what circumstances would that distinction be useful to the programmer?<br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div> Is there a difference, other than that there can only be one dest=
ructor?<br></div></div></blockquote><div><br>Well, if you look at the curre=
nt wording in the draft, it goes out of the way to specifically state it li=
ke I did, and I presumed you are not trying to change anything here.<br>Not=
e though that as I discussed in the other thread, I would be interested in =
changing the specification for this trait.<br> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Specializing <span style=
=3D"font-family:courier new,monospace">std::is_trivially_copyable<></=
span> would be fine, if the standard containers would be updated to have to=
obey it. Current implementations often directly use the compiler int=
rinsics or other tricks.<br></div></div></blockquote><div><br>As I argued i=
n the other thread, I think it would be a bad idea to let the user override=
this when is_memcpy_defined is false.<br>Specifically, if is_memcpy_define=
d<T>{} is false, then is_trivially_copyable<T>{} should be fals=
e independent of any user specializations.<br>To make this work, it would b=
e required that users don't specialize is_trivially_copyable.<br> </di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>There =
is already a case in current C++ where attributes change language semantics=
:<br></div></div></blockquote><div><br>I think this does not change the lan=
guage semantics as is understood by the committee members.<br>For it to hap=
pen, it would require that the attribute have an observable effect on the p=
rogram beyond<br>changing execution timing. For example, allowing an attrib=
ute to change the value of a trait, the size<br>of an object, overload reso=
lution, etc.<br>Making the program ill-formed in case the attribute is misu=
sed is not really changing the semantics.<br> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>My changes to =
standard-layout essentially just allow non-static data members at multiple =
levels of the hierarchy. This just makes it possible to implement som=
e data structures more easily. A simple example is <span style=3D"fon=
t-family:courier new,monospace">sockaddr</span>/<span style=3D"font-family:=
courier new,monospace">sockaddr_in</span>/<span style=3D"font-family:courie=
r new,monospace">sockaddr_<wbr>in6</span>/<span style=3D"font-family:courie=
r new,monospace">sockaddr_un</span>. Rather than having to go the C w=
ay of <span style=3D"font-family:courier new,monospace">reinterpret_cast</s=
pan>ing everywhere (or C-style casting), you can use C++ inheritance, and s=
till be able to pass the data to C when required.</div></div></blockquote><=
div><br>I see, can you provide one of your kitty examples here? Just to mak=
e things more clear.<br></div><div> </div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div>The current C++11/C++14 definition o=
f standard-layout permits deriving from standard-layout classes and remaini=
ng standard-layout, so long as you don't add any non-static data members or=
break the standard-layout rules. #6 is designed to extend that conce=
pt to a broader set of types. The standard-layout inheritance rule co=
mbined with other aspects of the Standard, such as <i>layout-compatible</i>=
, allow you to get away with things like using pointers of different class =
types than what was originally constructed. You can have a pointer to=
a C structure, <span style=3D"font-family:courier new,monospace">static_ca=
st</span> it to your derived class, and call member functions on it. =
So long as you don't care about the constructors and destructors, this will=
work, even if the object was originally constructed/initialized as the C s=
tructure.<br></div></div></blockquote><div><br>I see, well presumably you w=
ant this so you can create wrappers for C libraries, with no overhead, and =
still be able to freely mix the C style functions with the C++ style object=
s?<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2944_444535108.1411192897040--
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Sat, 20 Sep 2014 03:48:51 -0700 (PDT)
Raw View
------=_Part_3125_159510262.1411210131108
Content-Type: text/plain; charset=UTF-8
On Saturday, September 20, 2014 3:01:37 AM UTC-3, Matheus Izvekov wrote:
>
> Is there a difference, other than that there can only be one destructor?
>>
>
> Well, if you look at the current wording in the draft, it goes out of the
> way to specifically state it like I did, and I presumed you are not trying
> to change anything here.
>
By the way, I just realized why the standard is worded like that: deleted
destructor!
So it makes perfect sense that a class with deleted destructor would not be
trivially copyable if you think about it.
I tested this with clang and indeed they missed this distinction as well.
The following test program prints 1 instead of 0:
#include <iostream>
#include <type_traits>
struct foo {
int bar;
~foo() = delete;
};
int main() {
std::cout << std::is_trivially_copyable<foo>::value << std::endl;
return 0;
}
I already submitted this bug report to clang's bugtracker.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3125_159510262.1411210131108
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, September 20, 2014 3:01:37 AM UTC-3, Matheus =
Izvekov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div> Is the=
re a difference, other than that there can only be one destructor?<br></div=
></div></blockquote><div><br>Well, if you look at the current wording in th=
e draft, it goes out of the way to specifically state it like I did, and I =
presumed you are not trying to change anything here.<br></div></div></block=
quote><div><br>By the way, I just realized why the standard is worded like =
that: deleted destructor!<br><br>So it makes perfect sense that a class wit=
h deleted destructor would not be trivially copyable if you think about it.=
<br>I tested this with clang and indeed they missed this distinction as wel=
l.<br>The following test program prints 1 instead of 0:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
style=3D"color: #800;" class=3D"styled-by-prettify">#include</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #080;" class=3D"styled-by-prettify"><iostream></span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #800;" class=3D"styled-by-prettify">#include</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #080;=
" class=3D"styled-by-prettify"><type_traits></span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> foo </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> bar</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br> </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">~</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">delete</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> main</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br> std</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">cout </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><<</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">is_trivially_copyable</span><span style=3D=
"color: #080;" class=3D"styled-by-prettify"><foo></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">value </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify"><<</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">endl</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">0=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></di=
v><br>I already submitted this bug report to clang's bugtracker.<br><br><br=
></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3125_159510262.1411210131108--
.
Author: Myriachan <myriachan@gmail.com>
Date: Sat, 20 Sep 2014 21:45:48 -0700 (PDT)
Raw View
------=_Part_3761_411565741.1411274748048
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, September 19, 2014 11:01:37 PM UTC-7, Matheus Izvekov wrote:
>
> On Saturday, September 20, 2014 1:33:42 AM UTC-3, Myriachan wrote:
>>
>> OK, I like this design more than mine. =3D^-^=3D
>>
>> What about a requirement that all non-empty subobjects that do not have=
=20
>> any virtual base classes anywhere above themselves in the hierarchy (it'=
s=20
>> OK if *they* are a virtual base) are in contiguous bytes of memory and=
=20
>> have a fixed layout? I mean, so that you could do this without=20
>> implementation-defined / undefined behavior:
>>
>
> Yeah that is right, I missed specifying that :)
>
> Yes, this works. Should there also be a secondary trait class that=20
>> specifically means ones that are in the required category as opposed to=
=20
>> ones that are just optionally supported by the implementation?
>>
>
> I don't have any specific objection other than because I don't see why=20
> that would be important. In what circumstances would that distinction be=
=20
> useful to the programmer?=20
>
=20
>
I was simply thinking of a way in which a programmer could static_assert=20
that their code remained portable by the Standard's requirements regardless=
=20
of what extra support the current compiler and/or STL had. But this was=20
just a passing thought, and definitely is not important.
=20
> Is there a difference, other than that there can only be one destructor?
>>
>
> Well, if you look at the current wording in the draft, it goes out of the=
=20
> way to specifically state it like I did, and I presumed you are not tryin=
g=20
> to change anything here.
> Note though that as I discussed in the other thread, I would be intereste=
d=20
> in changing the specification for this trait.=20
>
=20
>
Nope, I didn't intend to change anything there.
=20
> Specializing std::is_trivially_copyable<> would be fine, if the standard=
=20
>> containers would be updated to have to obey it. Current implementations=
=20
>> often directly use the compiler intrinsics or other tricks.
>>
>
> As I argued in the other thread, I think it would be a bad idea to let th=
e=20
> user override this when is_memcpy_defined is false.
> Specifically, if is_memcpy_defined<T>{} is false, then=20
> is_trivially_copyable<T>{} should be false independent of any user=20
> specializations.
> To make this work, it would be required that users don't specialize=20
> is_trivially_copyable.
> =20
>
I was never strongly attached to this idea, so this would be fine. I agree=
=20
now that overriding is_trivially_copyable when is_memcpy_defined is false=
=20
would be a Bad Idea=E2=84=A2 in general.
=20
> There is already a case in current C++ where attributes change language=
=20
>> semantics:
>>
>
> I think this does not change the language semantics as is understood by=
=20
> the committee members.
> For it to happen, it would require that the attribute have an observable=
=20
> effect on the program beyond
> changing execution timing. For example, allowing an attribute to change=
=20
> the value of a trait, the size
> of an object, overload resolution, etc.
> Making the program ill-formed in case the attribute is misused is not=20
> really changing the semantics.=20
>
=20
The rule has always seemed a bit weird, since that's exactly what some of=
=20
the attributes compilers were already implementing do, and have to do. Now=
=20
GCC and Clang support [[gnu::meow]] in place of __attribute__((__meow__)).
My changes to standard-layout essentially just allow non-static data=20
>> members at multiple levels of the hierarchy. This just makes it possibl=
e=20
>> to implement some data structures more easily. A simple example is=20
>> sockaddr/sockaddr_in/sockaddr_in6/sockaddr_un. Rather than having to go=
=20
>> the C way of reinterpret_casting everywhere (or C-style casting), you=20
>> can use C++ inheritance, and still be able to pass the data to C when=20
>> required.
>>
>
> I see, can you provide one of your kitty examples here? Just to make=20
> things more clear.
>
It's a stretch, but all but the two most recent versions of the operating=
=20
system from which this file derives are named after cats:
http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
segment_command/_64, routines_command/_64, symtab_command... are all=20
"derived" from load_command in a sense. You know which one by the=20
load_command::cmd value (which is enum LoadCommandType). This could be=20
expressed as an inheritance relationship instead of the current=20
reinterpret_cast relationship, especially if it is combined with the=20
ability to reinterpret_cast derived classes even if they're not "actually"=
=20
that type, so long as aliasing problems would not occur. (This, for=20
example, could work if you read in the data as a big unsigned char array,=
=20
and all types involved were trivially-copyable in addition to being=20
standard-layout.)
=20
>
>> The current C++11/C++14 definition of standard-layout permits deriving=
=20
>> from standard-layout classes and remaining standard-layout, so long as y=
ou=20
>> don't add any non-static data members or break the standard-layout rules=
.. =20
>> #6 is designed to extend that concept to a broader set of types. The=20
>> standard-layout inheritance rule combined with other aspects of the=20
>> Standard, such as *layout-compatible*, allow you to get away with things=
=20
>> like using pointers of different class types than what was originally=20
>> constructed. You can have a pointer to a C structure, static_cast it to=
=20
>> your derived class, and call member functions on it. So long as you don=
't=20
>> care about the constructors and destructors, this will work, even if the=
=20
>> object was originally constructed/initialized as the C structure.
>>
>
> I see, well presumably you want this so you can create wrappers for C=20
> libraries, with no overhead, and still be able to freely mix the C style=
=20
> functions with the C++ style objects?
>
Mhmm, that's what it's for. It can also be used to write libraries in C++=
=20
that can be called using the lowest-common-denominator native interface,=20
which is generally C. Languages often support interfacing with C but not=
=20
C++, because C++ can be nearly impossible to interface with. After all,=20
the decision problem of simply whether an identifier is a type or a=20
non-type requires understanding almost the entire C++ language now.
Melissa
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_3761_411565741.1411274748048
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, September 19, 2014 11:01:37 PM UTC-7, M=
atheus Izvekov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Saturday, September 20, 2014 1:33:42 AM UTC-3, Myriachan wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>OK, I like th=
is design more than mine. =3D^-^=3D<br><br>What about a requirement that al=
l non-empty subobjects that do not have any virtual base classes anywhere a=
bove themselves in the hierarchy (it's OK if <i>they</i> are a virtual base=
) are in contiguous bytes of memory and have a fixed layout? I mean, =
so that you could do this without implementation-defined / undefined behavi=
or:<br></div></div></blockquote><div><br>Yeah that is right, I missed speci=
fying that :)<br><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>Yes, this works. Should there also be a secondary trait=
class that specifically means ones that are in the required category as op=
posed to ones that are just optionally supported by the implementation?<br>=
</div></div></blockquote><div><br>I don't have any specific objection other=
than because I don't see why that would be important. In what circumstance=
s would that distinction be useful to the programmer? <br></div></div></blo=
ckquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
</div></div></blockquote><div><br>I was simply thinking of a way in w=
hich a programmer could static_assert that their code remained portable by =
the Standard's requirements regardless of what extra support the current co=
mpiler and/or STL had. But this was just a passing thought, and defin=
itely is not important.<br> </div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div> Is there a difference, other than that there can only b=
e one destructor?<br></div></div></blockquote><div><br>Well, if you look at=
the current wording in the draft, it goes out of the way to specifically s=
tate it like I did, and I presumed you are not trying to change anything he=
re.<br>Note though that as I discussed in the other thread, I would be inte=
rested in changing the specification for this trait. <br></div></div></bloc=
kquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>&=
nbsp;</div></div></blockquote><div><br>Nope, I didn't intend to change anyt=
hing there.<br> </div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div=
>Specializing <span style=3D"font-family:courier new,monospace">std::is_tri=
vially_copyable<></span> would be fine, if the standard containers wo=
uld be updated to have to obey it. Current implementations often dire=
ctly use the compiler intrinsics or other tricks.<br></div></div></blockquo=
te><div><br>As I argued in the other thread, I think it would be a bad idea=
to let the user override this when is_memcpy_defined is false.<br>Specific=
ally, if is_memcpy_defined<T>{} is false, then is_trivially_copyable&=
lt;T>{} should be false independent of any user specializations.<br>To m=
ake this work, it would be required that users don't specialize is_triviall=
y_copyable.<br> </div></div></blockquote><div><br>I was never strongly=
attached to this idea, so this would be fine. I agree now that overr=
iding is_trivially_copyable when is_memcpy_defined is false would be a Bad =
Idea=E2=84=A2 in general.<br> </div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><div>There is already a case in current C++ where attributes chan=
ge language semantics:<br></div></div></blockquote><div><br>I think this do=
es not change the language semantics as is understood by the committee memb=
ers.<br>For it to happen, it would require that the attribute have an obser=
vable effect on the program beyond<br>changing execution timing. For exampl=
e, allowing an attribute to change the value of a trait, the size<br>of an =
object, overload resolution, etc.<br>Making the program ill-formed in case =
the attribute is misused is not really changing the semantics. </div><=
/div></blockquote><div> </div><div>The rule has always seemed a bit we=
ird, since that's exactly what some of the attributes compilers were alread=
y implementing do, and have to do. Now GCC and Clang support [[gnu::m=
eow]] in place of __attribute__((__meow__)).<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>My changes to stand=
ard-layout essentially just allow non-static data members at multiple level=
s of the hierarchy. This just makes it possible to implement some dat=
a structures more easily. A simple example is <span style=3D"font-fam=
ily:courier new,monospace">sockaddr</span>/<span style=3D"font-family:couri=
er new,monospace">sockaddr_in</span>/<span style=3D"font-family:courier new=
,monospace">sockaddr_<wbr>in6</span>/<span style=3D"font-family:courier new=
,monospace">sockaddr_un</span>. Rather than having to go the C way of=
<span style=3D"font-family:courier new,monospace">reinterpret_cast</span>i=
ng everywhere (or C-style casting), you can use C++ inheritance, and still =
be able to pass the data to C when required.</div></div></blockquote><div><=
br>I see, can you provide one of your kitty examples here? Just to make thi=
ngs more clear.<br></div></div></blockquote><div><br>It's a stretch, but al=
l but the two most recent versions of the operating system from which this =
file derives are named after cats:<br><br>http://llvm.org/docs/doxygen/html=
/Support_2MachO_8h_source.html<br><br>segment_command/_64, routines_command=
/_64, symtab_command... are all "derived" from load_command in a sense.&nbs=
p; You know which one by the load_command::cmd value (which is enum LoadCom=
mandType). This could be expressed as an inheritance relationship ins=
tead of the current reinterpret_cast relationship, especially if it is comb=
ined with the ability to reinterpret_cast derived classes even if they're n=
ot "actually" that type, so long as aliasing problems would not occur. =
; (This, for example, could work if you read in the data as a big unsigned =
char array, and all types involved were trivially-copyable in addition to b=
eing standard-layout.)<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div></div><div> </div><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>The current C++11/C++14 definition of=
standard-layout permits deriving from standard-layout classes and remainin=
g standard-layout, so long as you don't add any non-static data members or =
break the standard-layout rules. #6 is designed to extend that concep=
t to a broader set of types. The standard-layout inheritance rule com=
bined with other aspects of the Standard, such as <i>layout-compatible</i>,=
allow you to get away with things like using pointers of different class t=
ypes than what was originally constructed. You can have a pointer to =
a C structure, <span style=3D"font-family:courier new,monospace">static_cas=
t</span> it to your derived class, and call member functions on it. S=
o long as you don't care about the constructors and destructors, this will =
work, even if the object was originally constructed/initialized as the C st=
ructure.<br></div></div></blockquote><div><br>I see, well presumably you wa=
nt this so you can create wrappers for C libraries, with no overhead, and s=
till be able to freely mix the C style functions with the C++ style objects=
?<br></div></div></blockquote><div><br>Mhmm, that's what it's for. It=
can also be used to write libraries in C++ that can be called using the lo=
west-common-denominator native interface, which is generally C. Langu=
ages often support interfacing with C but not C++, because C++ can be nearl=
y impossible to interface with. After all, the decision problem of si=
mply whether an identifier is a type or a non-type requires understanding a=
lmost the entire C++ language now.<br><br>Melissa<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3761_411565741.1411274748048--
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Sun, 21 Sep 2014 01:55:36 -0700 (PDT)
Raw View
------=_Part_6_1139605392.1411289736034
Content-Type: text/plain; charset=UTF-8
On Sunday, September 21, 2014 1:45:48 AM UTC-3, Myriachan wrote:
>
> The rule has always seemed a bit weird, since that's exactly what some of
> the attributes compilers were already implementing do, and have to do. Now
> GCC and Clang support [[gnu::meow]] in place of __attribute__((__meow__)).
>
Yeah that is surprising to me. The last time I heard this being argued
about, there were objections on allowing vendor specific attributes which
violate those rules.
I didn't keep up with the discussion however, and now it seems the
situation is more hopeful than I thought :)
> It's a stretch, but all but the two most recent versions of the operating
> system from which this file derives are named after cats:
>
> http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
>
> segment_command/_64, routines_command/_64, symtab_command... are all
> "derived" from load_command in a sense. You know which one by the
> load_command::cmd value (which is enum LoadCommandType). This could be
> expressed as an inheritance relationship instead of the current
> reinterpret_cast relationship, especially if it is combined with the
> ability to reinterpret_cast derived classes even if they're not "actually"
> that type, so long as aliasing problems would not occur. (This, for
> example, could work if you read in the data as a big unsigned char array,
> and all types involved were trivially-copyable in addition to being
> standard-layout.)
>
Yeah I see what you mean now, I had thought about something like this
several years ago, would be a good idea indeed.
> Mhmm, that's what it's for. It can also be used to write libraries in C++
> that can be called using the lowest-common-denominator native interface,
> which is generally C. Languages often support interfacing with C but not
> C++, because C++ can be nearly impossible to interface with. After all,
> the decision problem of simply whether an identifier is a type or a
> non-type requires understanding almost the entire C++ language now.
>
Well sure, it's sometimes even difficult to interface C++ with C++ :)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6_1139605392.1411289736034
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, September 21, 2014 1:45:48 AM UTC-3, Myriachan =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></=
div><div>The rule has always seemed a bit weird, since that's exactly what =
some of the attributes compilers were already implementing do, and have to =
do. Now GCC and Clang support [[gnu::meow]] in place of __attribute__=
((__meow__)).<br></div></div></blockquote><div><br>Yeah that is surprising =
to me. The last time I heard this being argued about, there were objections=
on allowing vendor specific attributes which violate those rules.<br>I did=
n't keep up with the discussion however, and now it seems the situation is =
more hopeful than I thought :)<br> </div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div>It's a stretch, but all but the two m=
ost recent versions of the operating system from which this file derives ar=
e named after cats:<br><br><a href=3D"http://llvm.org/docs/doxygen/html/Sup=
port_2MachO_8h_source.html" target=3D"_blank" onmousedown=3D"this.href=3D'h=
ttp://www.google.com/url?q\75http%3A%2F%2Fllvm.org%2Fdocs%2Fdoxygen%2Fhtml%=
2FSupport_2MachO_8h_source.html\46sa\75D\46sntz\0751\46usg\75AFQjCNENI6eMDW=
f2WTyYxVUaJDX7AKyyLQ';return true;" onclick=3D"this.href=3D'http://www.goog=
le.com/url?q\75http%3A%2F%2Fllvm.org%2Fdocs%2Fdoxygen%2Fhtml%2FSupport_2Mac=
hO_8h_source.html\46sa\75D\46sntz\0751\46usg\75AFQjCNENI6eMDWf2WTyYxVUaJDX7=
AKyyLQ';return true;">http://llvm.org/docs/doxygen/<wbr>html/Support_2MachO=
_8h_source.<wbr>html</a><br><br>segment_command/_64, routines_command/_64, =
symtab_command... are all "derived" from load_command in a sense. You=
know which one by the load_command::cmd value (which is enum LoadCommandTy=
pe). This could be expressed as an inheritance relationship instead o=
f the current reinterpret_cast relationship, especially if it is combined w=
ith the ability to reinterpret_cast derived classes even if they're not "ac=
tually" that type, so long as aliasing problems would not occur. (Thi=
s, for example, could work if you read in the data as a big unsigned char a=
rray, and all types involved were trivially-copyable in addition to being s=
tandard-layout.)<br></div></div></blockquote><div><br>Yeah I see what you m=
ean now, I had thought about something like this several years ago, would b=
e a good idea indeed.<br> </div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div>Mhmm, that's what it's for. It can also =
be used to write libraries in C++ that can be called using the lowest-commo=
n-denominator native interface, which is generally C. Languages often=
support interfacing with C but not C++, because C++ can be nearly impossib=
le to interface with. After all, the decision problem of simply wheth=
er an identifier is a type or a non-type requires understanding almost the =
entire C++ language now.<br></div></div></blockquote><div><br>Well sure, it=
's sometimes even difficult to interface C++ with C++ :)<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_6_1139605392.1411289736034--
.
Author: Myriachan <myriachan@gmail.com>
Date: Tue, 21 Oct 2014 01:15:44 -0700 (PDT)
Raw View
------=_Part_2148_79726983.1413879345039
Content-Type: text/plain; charset=UTF-8
I feel bad for bringing offsetof up again, but the big thread on
std-discussion ended with a conclusion that trivial types ought to allow
offsetof, because there cannot be a technical reason why not to allow
it--if that the rest of the Standard is being followed.
The end result was that the fact that all trivial types are permitted with
be in a union without a constructor along with the definition of an
object's lifetime (which specifically mentions trivial types) results in
there necessarily existing a fixed integer for each member that we can call
offsetof. I ended up admitting that trivially-copyable non-standard-layout
types can theoretically be implemented in a way that complies with the
Standard yet such types don't have a meaningful offsetof. However, trivial
non-standard-layout types--as opposed to the less-strict
"trivially-copyable"--can't work this way without breaking some other part
of the Standard.
I conclude that there is no reason to continue to disallow offsetof on
trivial types, and I think that restriction should be relaxed.
Here're the changes I think are appropriate:
1. offsetof would be well-defined for all trivial classes and all
standard-layout classes, subject to the below.
2. offsetof(C, m) would be well-defined for all
non-base-class-subobjects subobjects m of class C, not just direct
members. This means that there is a "chain" of sorts.
3. offsetof(C, m) would be well-defined for elements of array members
(or array members of subobjects as above) so long as the index is 0 through
one past the last element, as usual.
4. The relative values of offsetof(C, m) and offsetof(C, n) are only
specified in general for m and n of the same access-specifier. This is new
because it was irrelevant to standard-layout classes by definition.
5. The behavior of using offsetof on a sequence of member-access / array
index operators would be undefined if any specified member is of reference
type, or if a pointer member access operator is used (-> or ->*). This is
new; the existing Standard does not mention that offsetof is undefined on
reference members, when it clearly ought to be. (offsetof on a reference
type makes no sense, unless you want to force the underlying representation
of a reference to be a pointer, which isn't required, and we wouldn't want
to require.)
6. Using member pointers in an offsetof would be defined, so long as the
usual rules are met.
7. offsetof(C, m) would be a constant-expression if all member access
expressions involving values (operators .* and []) are given
constant-expressions as parameters. This is new, but logical. Although
I've heard of no such thing, this is technically a breaking change;
compilers could previously move offsets around at runtime.
8. offsetof(C, m) would be prohibited in certain class contexts, like
sizeof is. I.e. struct Meow { int y; char x[40 - offsetof(Meow, y)]; };
This is just formalization of what had previously been left unspecified. I
dunno, this seems to make sense.
9. offsetof(U, m) would be equal to offsetof(U, n) for all top-level
members m and n of union U. (Does the Standard require it to specifically
equal 0?)
10. For "C *c; SomeType C::*pm = &C::m;", "c->*pm = v;" would be
equivalent to "std::memcpy(reinterpret_cast<unsigned char *>(c) +
offsetof(C, m), &v, sizeof(SomeType))". (At least whenever the Standard
considers offsetof defined, which is why we know memcpy is safe: it's a
trivial type.) Not literally that this is always true, but I think you all
get the point =^-^=
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2148_79726983.1413879345039
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I feel bad for bringing offsetof up again, but the big thr=
ead on=20
std-discussion ended with a conclusion that trivial types ought to allow
offsetof, because there cannot be a technical reason why not to allow=20
it--if that the rest of the Standard is being followed.<br><br>The end=20
result was that the fact that all trivial types are permitted with be in
a union without a constructor along with the definition of an object's=20
lifetime (which specifically mentions trivial types) results in there=20
necessarily existing a fixed integer for each member that we can call=20
offsetof. I ended up admitting that trivially-copyable=20
non-standard-layout types can theoretically be implemented in a way that
complies with the Standard yet such types don't have a meaningful=20
offsetof. However, trivial non-standard-layout types--as opposed to t=
he
less-strict "trivially-copyable"--can't work this way without breaking=20
some other part of the Standard.<br><br>I conclude that there is no=20
reason to continue to disallow offsetof on trivial types, and I think=20
that restriction should be relaxed.<br><br>Here're the changes I think are =
appropriate:<br><br><ol><li>offsetof would be well-defined for all trivial =
classes and all standard-layout classes, subject to the below.<br></li><li>=
offsetof(C, m) would be well-defined for all non-base-class-subobjects subo=
bjects m of class C, not just direct members. This means that there i=
s a "chain" of sorts.<br></li><li>offsetof(C, m) would be well-defined for =
elements of array members (or array members of subobjects as above) so long=
as the index is 0 through one past the last element, as usual.</li><li>The=
relative values of offsetof(C, m) and offsetof(C, n) are only specified in=
general for m and n of the same access-specifier. This is new becaus=
e it was irrelevant to standard-layout classes by definition.<br></li><li>T=
he behavior of using offsetof on a sequence of member-access / array index =
operators would be undefined if any specified member is of reference type, =
or if a pointer member access operator is used (-> or ->*). Thi=
s is new; the existing Standard does not mention that offsetof is undefined=
on reference members, when it clearly ought to be. (offsetof on a re=
ference type makes no sense, unless you want to force the underlying repres=
entation of a reference to be a pointer, which isn't required, and we would=
n't want to require.)<br></li><li>Using member pointers in an offsetof woul=
d be defined, so long as the usual rules are met.</li><li>offsetof(C, m) wo=
uld be a constant-expression if all member access expressions involving val=
ues (operators .* and []) are given constant-expressions as parameters.&nbs=
p; This is new, but logical. Although I've heard of no such thing, th=
is is technically a breaking change; compilers could previously move offset=
s around at runtime.<br></li><li>offsetof(C, m) would be prohibited in cert=
ain class contexts, like sizeof is. I.e. struct Meow { int y; char x[=
40 - offsetof(Meow, y)]; }; This is just formalization of what had pr=
eviously been left unspecified. I dunno, this seems to make sense.<br=
></li><li>offsetof(U, m) would be equal to offsetof(U, n) for all top-level=
members m and n of union U. (Does the Standard require it to specifi=
cally equal 0?)</li><li>For "C *c; SomeType C::*pm =3D &C::m;", "c->=
*pm =3D v;" would be equivalent to "std::memcpy(reinterpret_cast<unsigne=
d char *>(c) + offsetof(C, m), &v, sizeof(SomeType))". (At lea=
st whenever the Standard considers offsetof defined, which is why we know m=
emcpy is safe: it's a trivial type.) Not literally that this is alway=
s true, but I think you all get the point =3D^-^=3D</li></ol><p>Melissa<br>=
</p></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2148_79726983.1413879345039--
.
Author: Matheus Izvekov <mizvekov@gmail.com>
Date: Tue, 21 Oct 2014 20:56:30 -0700 (PDT)
Raw View
------=_Part_5141_1586070460.1413950190245
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 21, 2014 6:15:45 AM UTC-2, Myriachan wrote:
>
> I conclude that there is no reason to continue to disallow offsetof on
> trivial types, and I think that restriction should be relaxed.
>
But still, that only seems like a marginal improvement on the current
situation.
I am assuming we are interested in such a change for the same reason: we
want something like container_of that works with as many types as possible,
mostly in order to support intrusive containers.
It seems like what we need is just a generalization of the existing
downcast rules.
Currently they only define base to derived conversions, but it's probably
not far fetched to extend it so member to container conversions are also
defined.
But this would also require a new operator to make use of such a facility
of course...
Anyway, such a proposal would not need to touch offsetof at all.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5141_1586070460.1413950190245
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, October 21, 2014 6:15:45 AM UTC-2, Myriachan w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">I conclu=
de that there is no=20
reason to continue to disallow offsetof on trivial types, and I think=20
that restriction should be relaxed.<br></div></blockquote><div><br>But stil=
l, that only seems like a marginal improvement on the current situation.<br=
>I am assuming we are interested in such a change for the same reason: we w=
ant something like container_of that works with as many types as possible, =
mostly in order to support intrusive containers.<br>It seems like what we n=
eed is just a generalization of the existing downcast rules.<br>Currently t=
hey only define base to derived conversions, but it's probably not far fetc=
hed to extend it so member to container conversions are also defined.<br>Bu=
t this would also require a new operator to make use of such a facility of =
course...<br><br>Anyway, such a proposal would not need to touch offsetof a=
t all.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5141_1586070460.1413950190245--
.
Author: Myriachan <myriachan@gmail.com>
Date: Tue, 21 Oct 2014 21:06:10 -0700 (PDT)
Raw View
------=_Part_677_444631196.1413950770573
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 21, 2014 8:56:30 PM UTC-7, Matheus Izvekov wrote:
>
> On Tuesday, October 21, 2014 6:15:45 AM UTC-2, Myriachan wrote:
>>
>> I conclude that there is no reason to continue to disallow offsetof on
>> trivial types, and I think that restriction should be relaxed.
>>
>
> But still, that only seems like a marginal improvement on the current
> situation.
> I am assuming we are interested in such a change for the same reason: we
> want something like container_of that works with as many types as possible,
> mostly in order to support intrusive containers.
>
>
Yes on both counts. I would love to see the entire memory model overhauled
to reflect practice, and things like this are part of it. I feel that such
a thing would never fly with the C or C++ Committees, though. I'm just a
tiny voice among the many programmers of the world.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_677_444631196.1413950770573
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, October 21, 2014 8:56:30 PM UTC-7, Matheus Izv=
ekov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On=
Tuesday, October 21, 2014 6:15:45 AM UTC-2, Myriachan wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr">I conclude that there is no=20
reason to continue to disallow offsetof on trivial types, and I think=20
that restriction should be relaxed.<br></div></blockquote><div><br>But stil=
l, that only seems like a marginal improvement on the current situation.<br=
>I am assuming we are interested in such a change for the same reason: we w=
ant something like container_of that works with as many types as possible, =
mostly in order to support intrusive containers.<br><br></div></div></block=
quote><div><br>Yes on both counts. I would love to see the entire mem=
ory model overhauled to reflect practice, and things like this are part of =
it. I feel that such a thing would never fly with the C or C++ Commit=
tees, though. I'm just a tiny voice among the many programmers of the=
world.<br><br>Melissa<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_677_444631196.1413950770573--
.