220 12691 <c11dc8b4-df55-4530-9322-b6bd5de9ce54@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: Myriachan <myriachan@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Usability extensions to offsetof
Date: Thu, 4 Sep 2014 20:49:52 -0700 (PDT)
Lines: 304
Approved: news@gmane.org
Message-ID: <c11dc8b4-df55-4530-9322-b6bd5de9ce54@isocpp.org>
References: <fc4c748a-1805-4e92-ae3f-58bbfe6b7537@isocpp.org> <1790122.GP859xiMW3@tjmaciei-mobl4> <dedaddc6-c382-4256-83a9-6af4dbd91caf@isocpp.org>
 <3079502.NAEi170Di4@tjmaciei-mobl4>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; 
	boundary="----=_Part_369_411316699.1409888992441"
X-Trace: ger.gmane.org 1409889003 31772 80.91.229.3 (5 Sep 2014 03:50:03 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Fri, 5 Sep 2014 03:50:03 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDKLT4PURQHRBYXFUSQAKGQE4ESLQCQ@isocpp.org Fri Sep 05 05:49:56 2014
Return-path: <std-proposals+bncBDKLT4PURQHRBYXFUSQAKGQE4ESLQCQ@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-yh0-f72.google.com ([209.85.213.72])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDKLT4PURQHRBYXFUSQAKGQE4ESLQCQ@isocpp.org>)
	id 1XPkX6-0007WE-2J
	for gclcip-std-proposals@m.gmane.org; Fri, 05 Sep 2014 05:49:56 +0200
Original-Received: by mail-yh0-f72.google.com with SMTP id f73sf38192663yha.11
        for <gclcip-std-proposals@m.gmane.org>; Thu, 04 Sep 2014 20:49:55 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe
         :content-type;
        bh=Ng8X6OqpBNWn/YcLV1QF/DTozr9XllRR/bzKIe1pZGc=;
        b=r+r8xKDAKtvhUmJ80n54xjSJcnH0JXLnhd6ok2CzGTyswGbxD84CSREd30d+2G3dG2
         a7DneR0VYDS7AaQKiox7P5DdsuEPyqxldzR3FXK+wj0hihLXPAZod1unacPqK1E1tnCA
         6DDiOlkcsIcBNo42T7fkISv7nKoX6hr1ME+lBnDd0k0AhP6hMo5/ZPD2Hy3f+sHd+D35
         uE6jcRSl2THZrqwi4gkpltkE8qTtAFE6nbzbgZI8rIkNGaZF5NW/nVtOFlmVoHiGvzYr
         HWaopm7zw9G6YFHPH8AJ9UyRrvLr2Hhp8l8wThKwcF5q48ZmPCtooE8pkwsr3ViwD7sU
         TqnA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe:content-type;
        bh=Ng8X6OqpBNWn/YcLV1QF/DTozr9XllRR/bzKIe1pZGc=;
        b=VfmbR7w1edV+UuIahQ9SRYjiJB4KhJuFZE4Y/X1/gza6fX2gqPDxMtRiycWnk+rHhb
         MWqYkdUanKXDcjpPxnfZngYlMxjJ8m00ed68KThpt2jJGUJZc4llAGqIUyEPofZfv+Vc
         GZuuhsQcM+wtbXDNUQ5iaP8PLS5UyMyGJZ3I968O+fSdSdmyonTTyImBkDYIokLqNCsg
         L8El59SWOdzQYAKedXpqV/uwRYcy0F7EZHLKth8S9uCrK1P18qcCvqeHpbFqnmainTDX
         zqU6A2hFj0KEfvWcaEGmnmbHVBpzrVhKNmc9h1NRx2xU54werZsZuNHxVNNdLG2gSNag
         q0ew==
X-Gm-Message-State: ALoCoQlDCe4yr1HFLMGzOoroXUk/btZf1EZI4j86BStROSgx0JD9IRdrx92obWQvIJ7Uixu8b4pr
X-Received: by 10.224.21.129 with SMTP id j1mr5301622qab.7.1409888994995;
        Thu, 04 Sep 2014 20:49:54 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.50.222.38 with SMTP id qj6ls64437igc.9.canary; Thu, 04 Sep
 2014 20:49:54 -0700 (PDT)
X-Received: by 10.50.114.69 with SMTP id je5mr7851igb.1.1409888994358;
        Thu, 04 Sep 2014 20:49:54 -0700 (PDT)
In-Reply-To: <3079502.NAEi170Di4@tjmaciei-mobl4>
X-Original-Sender: myriachan@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:12691
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/12691>

------=_Part_369_411316699.1409888992441
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Thursday, September 4, 2014 1:04:27 PM UTC-7, Thiago Macieira wrote:
>
> On Thursday 04 September 2014 12:19:38 Myriachan wrote:=20
> > There isn't a Standard way of determining whether a class has virtual=
=20
> > inheritance, however.  is_offsetof_compatible would help with this, and=
=20
> > would be useful in more cases than merely standard-layout.  Although,=
=20
> > actually, *are* there cases in which virtual inheritance breaks=20
> offsetof?=20
>
> All of them. Any member in the virtual base has a non-fixed position in=
=20
> the=20
> derived class.=20
>
> struct Base { int i; };=20
> struct VirtualBase { int j; };=20
> struct Derived : public Base, public virtual VirtualBase {};=20
> struct Derived2 : public Derived { int k; };=20
>
> The VirtualBase sub-object is allocated in different positions in Derived=
=20
> and=20
> in Derived2.=20
>
> Which is why you can't write this:=20
>
> int Derived:: ptr() { return &Derived::j; }=20
>
> Clang:=20
> error: conversion from pointer to member of class 'VirtualBase' to pointe=
r=20
> to=20
> member of class 'Derived' via virtual base 'VirtualBase' is not allowed=
=20
>
> GCC:=20
> pointer to member conversion via virtual base =E2=80=98VirtualBase=E2=80=
=99=20
>
> ICC:=20
> error: cannot convert pointer to member of base class "VirtualBase" to=20
> pointer=20
> to member of derived class "Derived" -- base class is virtual=20
>
>
> The point is that Derived is not standard-layout, so you can't use=20
> offsetof in=20
> it. =20


offsetof *can* be meaningful in virtual-inheritance classes, so long as you=
=20
don't try to use it on anything but the exact same dynamic type.  (I think=
=20
"dynamic type" is the right term.)  That it's chosen not to be meaningful=
=20
is another story.
=20

>
> The following classes are not standard layout either:=20
> struct S1=20
> {=20
>         int i;=20
> protected:=20
>         int j;=20
> };=20
>
> struct S2=20
> {=20
>         int i;=20
>         virtual ~S2();=20
> };=20
>
> Though on most ABIs their layout is well-defined: it's actually "what=20
> you'd=20
> expect" for S1 and for S2 there's an extra pointer somewhere in the=20
> struct.=20
>

For the next part, I'm going to ignore inheritance, because offsets are not=
=20
directly usable with inheritance.  Only standard-layout types guarantee=20
that the offset of a base class is zero, and there's no reason to object to=
=20
this.

In the case of S1, or rather, any trivially-copyable but=20
non-standard-layout type, it is formally provably only incompatible with=20
offsetof because the Standard says so.  Although it does not work with=20
constexpr because "says so", you can use the pointer arithmetic behind=20
offsetof with class S1 and it will work in all implementations.  The fact=
=20
that std::memmove works and is not a magic function - it can be=20
reimplemented in C++ itself outside the STL - implies this.  Some unsigned=
=20
char * pointers formed during a simple for-loop memmove implementation will=
=20
eventually equal each of the members of a class, and static_cast<std::size_=
t>(current_dest=20
- start_dest) is equal to those offsets.  Because std::memmove necessarily=
=20
works on the subobjects (because trivially-copyable is recursive), such=20
offsets must actually be usable.

This argument actually works with *any* type under certain reasonable=20
assumptions:
 * Objects occupy contiguous regions of unsigned char * memory.
 * All instances of the same "dynamic type" have the same memory layout. =
=20
That is, an implementation won't decide that when bit 3 of the address is=
=20
1, members x and y are swapped in memory.

The former is *sort of* guaranteed when using placement new; it can only=20
break if the implementation moves an object "somewhere else" for the=20
duration despite the placement new.


> Though I'm going to say that a PMF is a superior solution to offsetof=20
> since it=20
> works on both cases and is a language construct. If we're given the=20
> ability to=20
> go back to the containing object, I don't think I'll ever need offsetof=
=20
> again.=20
>

There are still things that member pointers don't allow and offsetof does,=
=20
even with standard-layout classes, such as member pointers to elements of=
=20
member arrays, and member pointers to subobjects of members.  Also, member=
=20
pointers cannot be used with unsigned char * / void *, whereas offsetof can=
=20
be.  Adding an empty base class to resolve the inability to use void * with=
=20
member pointers isn't always possible: you may be doing aggregate=20
initialization.  (There's another proposal on relaxing that somewhere.)

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_369_411316699.1409888992441
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, September 4, 2014 1:04:27 PM UTC-7, Thiago Ma=
cieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thursday 04 Se=
ptember 2014 12:19:38 Myriachan wrote:
<br>&gt; There isn't a Standard way of determining whether a class has virt=
ual=20
<br>&gt; inheritance, however. &nbsp;is_offsetof_compatible would help with=
 this, and=20
<br>&gt; would be useful in more cases than merely standard-layout. &nbsp;A=
lthough,=20
<br>&gt; actually, *are* there cases in which virtual inheritance breaks of=
fsetof?
<br>
<br>All of them. Any member in the virtual base has a non-fixed position in=
 the=20
<br>derived class.
<br>
<br>struct Base { int i; };
<br>struct VirtualBase { int j; };
<br>struct Derived : public Base, public virtual VirtualBase {};
<br>struct Derived2 : public Derived { int k; };
<br>
<br>The VirtualBase sub-object is allocated in different positions in Deriv=
ed and=20
<br>in Derived2.
<br>
<br>Which is why you can't write this:
<br>
<br>int Derived:: ptr() { return &amp;Derived::j; }
<br>
<br>Clang:
<br>error: conversion from pointer to member of class 'VirtualBase' to poin=
ter to=20
<br>member of class 'Derived' via virtual base 'VirtualBase' is not allowed
<br>
<br>GCC:
<br>pointer to member conversion via virtual base =E2=80=98VirtualBase=E2=
=80=99
<br>
<br>ICC:
<br>error: cannot convert pointer to member of base class "VirtualBase" to =
pointer=20
<br>to member of derived class "Derived" -- base class is virtual
<br>
<br>
<br>The point is that Derived is not standard-layout, so you can't use offs=
etof in=20
<br>it.
&nbsp;</blockquote><div><br>offsetof <i>can</i> be meaningful in virtual-in=
heritance classes, so long as you don't try to use it on anything but the e=
xact same dynamic type.&nbsp; (I think "dynamic type" is the right term.)&n=
bsp; That it's chosen not to be meaningful is another story.<br>&nbsp;</div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">
<br>The following classes are not standard layout either:
<br>struct S1
<br>{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i;
<br>protected:
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int j;
<br>};
<br>
<br>struct S2
<br>{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual ~S2();
<br>};
<br>
<br>Though on most ABIs their layout is well-defined: it's actually "what y=
ou'd=20
<br>expect" for S1 and for S2 there's an extra pointer somewhere in the str=
uct.
<br></blockquote><div><br>For the next part, I'm going to ignore inheritanc=
e, because offsets are not directly usable with inheritance.&nbsp; Only sta=
ndard-layout types guarantee that the offset of a base class is zero, and t=
here's no reason to object to this.<br><br>In the case of S1, or rather, an=
y trivially-copyable but non-standard-layout type, it is formally provably =
only incompatible with <span style=3D"font-family: courier new,monospace;">=
offsetof</span> because the Standard says so.&nbsp; Although it does not wo=
rk with <span style=3D"font-family: courier new,monospace;">constexpr</span=
> because "says so", you can use the pointer arithmetic behind <span style=
=3D"font-family: courier new,monospace;">offsetof</span> with class S1 and =
it will work in all implementations.&nbsp; The fact that <span style=3D"fon=
t-family: courier new,monospace;">std::memmove</span> works and is not a ma=
gic function - it can be reimplemented in C++ itself outside the STL - impl=
ies this.&nbsp; Some <span style=3D"font-family: courier new,monospace;">un=
signed char *</span> pointers formed during a simple <span style=3D"font-fa=
mily: courier new,monospace;">for</span>-loop <span style=3D"font-family: c=
ourier new,monospace;">memmove</span> implementation will eventually equal =
each of the members of a class, and <span style=3D"font-family: courier new=
,monospace;">static_cast&lt;std::size_t&gt;(current_dest - start_dest)</spa=
n> is equal to those offsets.&nbsp; Because <span style=3D"font-family: cou=
rier new,monospace;">std::memmove</span> necessarily works on the subobject=
s (because trivially-copyable is recursive), such offsets must actually be =
usable.<br><br>This argument actually works with <i>any</i> type under cert=
ain reasonable assumptions:<br>&nbsp;* Objects occupy contiguous regions of=
 <span style=3D"font-family: courier new,monospace;">unsigned char *</span>=
 memory.<br>&nbsp;* All instances of the same "dynamic type" have the same =
memory layout.&nbsp; That is, an implementation won't decide that when bit =
3 of the address is 1, members x and y are swapped in memory.<br><br>The fo=
rmer is <i>sort of</i> guaranteed when using placement <span style=3D"font-=
family: courier new,monospace;">new</span>; it can only break if the implem=
entation moves an object "somewhere else" for the duration despite the plac=
ement <span style=3D"font-family: courier new,monospace;">new</span>.<br><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>Though I'm going to say that a PMF is a superior solution to offsetof s=
ince it=20
<br>works on both cases and is a language construct. If we're given the abi=
lity to=20
<br>go back to the containing object, I don't think I'll ever need offsetof=
 again.
<br></blockquote><div><br>There are still things that member pointers don't=
 allow and offsetof does, even with standard-layout classes, such as member=
 pointers to elements of member arrays, and member pointers to subobjects o=
f members.&nbsp; Also, member pointers cannot be used with unsigned char * =
/ void *, whereas offsetof can be.&nbsp; Adding an empty base class to reso=
lve the inability to use void * with member pointers isn't always possible:=
 you may be doing aggregate initialization.&nbsp; (There's another proposal=
 on relaxing that somewhere.)<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&quot; 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_369_411316699.1409888992441--

.
