Topic: void member variables


Author: andrew.gilewsky@gmail.com
Date: Sun, 15 Mar 2015 02:38:52 -0700 (PDT)
Raw View
------=_Part_2354_34217773.1426412332395
Content-Type: multipart/alternative;
 boundary="----=_Part_2355_1719977062.1426412332395"

------=_Part_2355_1719977062.1426412332395
Content-Type: text/plain; charset=UTF-8

Right now there is no good way to conditionally include member variable
into a structure definition. This ability is important, for example, to
avoid allocating space for empty members and thus bloating structure size
(example: generic container with user-defined allocator; allocator is often
an empty structure).

Motivating example 1 - container with allocator:
template<typename T, typename Al> struct my_container {
  T *data;
  Al alloc; // bloats structure size unnecessarily if allocator is empty!
};
static_assert(sizeof(my_container<int, my_stateless_alloc>) > sizeof(int*),
"");

Motivating example 2 - serialized messages:
enum message_type { MT_INT, MT_EMPTY };
struct message_header { message_type t; };

template<message_type Type> struct message_payload;
template<> struct message_payload<MT_INT>   { int data; };
template<> struct message_payload<MT_EMPTY> {};

template<message_type Type> struct message {
  message_header header;
  message_payload<Type> payload; // wastes space for empty payloads!
};
static_assert(sizeof(message<MT_EMPTY>) > sizeof(message_header), "");

Currently used workarounds are based on supplemental template structure
with dispatch based on is_empty<> result. Examples above are rewritten as:
template<bool IsEmpty, typename Al> struct my_container_base { Al al; };
template<typename Al> struct my_container_base < true, Al > {};
template<typename T, typename Al> struct my_container : public
my_container_base<std::is_empty<Al>::value, Al> {
  T* data; // useful data is now offset from the beginning of my_container
structure; in general case it could be undesired - for example, it could
make us touch an extra cache line on fast path in some cases
};

template<bool IsEmpty, typename Payload> struct message_impl {
  message_header header;
  Payload payload;
};
template<typename Payload> struct message_impl<true, Payload> {
  message_header header; // here order is really important, so
inheritance/empty-base-class-optimization can't be used; we have to write
same things twice
};
template<message_type Type> struct message : public
message_impl<std::is_empty<message_payload<Type>>::value,
message_payload<Type>> {};

This workaround scales poorly if there are several potentially empty
template parameters.

The proposal is to add a construct (member variable with type "void") that
would essentially be skipped by the compiler without affecting structure
layout. Accessing such member variable (value or address) would be a
compile-time error. Then code pieces above could be rewritten like this:
template<typename T> using nonempty_only =
std::conditional_t<std::is_empty<T>::value, void, T>;
template<typename T, typename Al> struct my_container {
  T *data;
  nonempty_only<Al> alloc; // won't affect layout if Al is empty
};
template<message_type Type> struct message {
  message_header header;
  nonempty_only<message_payload<Type>> payload;
};

--

---
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_2355_1719977062.1426412332395
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Right now there is no good way to conditionally include me=
mber variable into a structure definition. This ability is important, for e=
xample, to avoid allocating space for empty members and thus bloating struc=
ture size (example: generic container with user-defined allocator; allocato=
r is often an empty structure).<br><br>Motivating example 1 - container wit=
h allocator:<br>template&lt;typename T, typename Al&gt; struct my_container=
 {<br>&nbsp; T *data;<br>&nbsp; Al alloc; // bloats structure size unnecess=
arily if allocator is empty!<br>};<br>static_assert(sizeof(my_container&lt;=
int, my_stateless_alloc&gt;) &gt; sizeof(int*), "");<br><br>Motivating exam=
ple 2 - serialized messages:<br>enum message_type { MT_INT, MT_EMPTY };<br>=
struct message_header { message_type t; };<br><br>template&lt;message_type =
Type&gt; struct message_payload;<br>template&lt;&gt; struct message_payload=
&lt;MT_INT&gt;&nbsp;&nbsp; { int data; };<br>template&lt;&gt; struct messag=
e_payload&lt;MT_EMPTY&gt; {};<br><br>template&lt;message_type Type&gt; stru=
ct message {<br>&nbsp; message_header header;<br>&nbsp; message_payload&lt;=
Type&gt; payload; // wastes space for empty payloads!<br>};<br>static_asser=
t(sizeof(message&lt;MT_EMPTY&gt;) &gt; sizeof(message_header), "");<br><br>=
Currently used workarounds are based on supplemental template structure wit=
h dispatch based on is_empty&lt;&gt; result. Examples above are rewritten a=
s:<br>template&lt;bool IsEmpty, typename Al&gt; struct my_container_base { =
Al al; };<br>template&lt;typename Al&gt; struct my_container_base &lt; true=
, Al &gt; {};<br>template&lt;typename T, typename Al&gt; struct my_containe=
r : public my_container_base&lt;std::is_empty&lt;Al&gt;::value, Al&gt; {<br=
>&nbsp; T* data; // useful data is now offset from the beginning of my_cont=
ainer structure; in general case it could be undesired - for example, it co=
uld make us touch an extra cache line on fast path in some cases<br>};<br><=
br>template&lt;bool IsEmpty, typename Payload&gt; struct message_impl {<br>=
&nbsp; message_header header;<br>&nbsp; Payload payload;<br>};<br>template&=
lt;typename Payload&gt; struct message_impl&lt;true, Payload&gt; {<br>&nbsp=
; message_header header; // here order is really important, so inheritance/=
empty-base-class-optimization can't be used; we have to write same things t=
wice<br>};<br>template&lt;message_type Type&gt; struct message : public mes=
sage_impl&lt;std::is_empty&lt;message_payload&lt;Type&gt;&gt;::value, messa=
ge_payload&lt;Type&gt;&gt; {};<br><br>This workaround scales poorly if ther=
e are several potentially empty template parameters.<br><br>The proposal is=
 to add a construct (member variable with type "void") that would essential=
ly be skipped by the compiler without affecting structure layout. Accessing=
 such member variable (value or address) would be a compile-time error. The=
n code pieces above could be rewritten like this:<br>template&lt;typename T=
&gt; using nonempty_only =3D std::conditional_t&lt;std::is_empty&lt;T&gt;::=
value, void, T&gt;;<br>template&lt;typename T, typename Al&gt; struct my_co=
ntainer {<br>&nbsp; T *data;<br>&nbsp; nonempty_only&lt;Al&gt; alloc; // wo=
n't affect layout if Al is empty<br>};<br>template&lt;message_type Type&gt;=
 struct message {<br>&nbsp; message_header header;<br>&nbsp; nonempty_only&=
lt;message_payload&lt;Type&gt;&gt; payload;<br>};<br><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&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_2355_1719977062.1426412332395--
------=_Part_2354_34217773.1426412332395--

.


Author: Marc <marc.glisse@gmail.com>
Date: Sun, 15 Mar 2015 04:01:02 -0700 (PDT)
Raw View
------=_Part_2498_166031743.1426417262741
Content-Type: multipart/alternative;
 boundary="----=_Part_2499_914247148.1426417262741"

------=_Part_2499_914247148.1426417262741
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Le dimanche 15 mars 2015 10:38:52 UTC+1, andrew....@gmail.com a =C3=A9crit =
:
>
> Right now there is no good way to conditionally include member variable=
=20
> into a structure definition. This ability is important, for example, to=
=20
> avoid allocating space for empty members and thus bloating structure size=
=20
> (example: generic container with user-defined allocator; allocator is oft=
en=20
> an empty structure).
>
> Motivating example 1 - container with allocator:
> template<typename T, typename Al> struct my_container {
>   T *data;
>   Al alloc; // bloats structure size unnecessarily if allocator is empty!
> };
> static_assert(sizeof(my_container<int, my_stateless_alloc>) >=20
> sizeof(int*), "");
>
> Motivating example 2 - serialized messages:
> enum message_type { MT_INT, MT_EMPTY };
> struct message_header { message_type t; };
>
> template<message_type Type> struct message_payload;
> template<> struct message_payload<MT_INT>   { int data; };
> template<> struct message_payload<MT_EMPTY> {};
>
> template<message_type Type> struct message {
>   message_header header;
>   message_payload<Type> payload; // wastes space for empty payloads!
> };
> static_assert(sizeof(message<MT_EMPTY>) > sizeof(message_header), "");
>
> Currently used workarounds are based on supplemental template structure=
=20
> with dispatch based on is_empty<> result. Examples above are rewritten as=
:
> template<bool IsEmpty, typename Al> struct my_container_base { Al al; };
> template<typename Al> struct my_container_base < true, Al > {};
> template<typename T, typename Al> struct my_container : public=20
> my_container_base<std::is_empty<Al>::value, Al> {
>   T* data; // useful data is now offset from the beginning of my_containe=
r=20
> structure; in general case it could be undesired - for example, it could=
=20
> make us touch an extra cache line on fast path in some cases
> };
>
> template<bool IsEmpty, typename Payload> struct message_impl {
>   message_header header;
>   Payload payload;
> };
> template<typename Payload> struct message_impl<true, Payload> {
>   message_header header; // here order is really important, so=20
> inheritance/empty-base-class-optimization can't be used; we have to write=
=20
> same things twice
> };
> template<message_type Type> struct message : public=20
> message_impl<std::is_empty<message_payload<Type>>::value,=20
> message_payload<Type>> {};
>
> This workaround scales poorly if there are several potentially empty=20
> template parameters.
>
> The proposal is to add a construct (member variable with type "void") tha=
t=20
> would essentially be skipped by the compiler without affecting structure=
=20
> layout. Accessing such member variable (value or address) would be a=20
> compile-time error. Then code pieces above could be rewritten like this:
> template<typename T> using nonempty_only =3D=20
> std::conditional_t<std::is_empty<T>::value, void, T>;
> template<typename T, typename Al> struct my_container {
>   T *data;
>   nonempty_only<Al> alloc; // won't affect layout if Al is empty
> };
> template<message_type Type> struct message {
>   message_header header;
>   nonempty_only<message_payload<Type>> payload;
> };
>

Not being able to use the empty member (call its member functions) looks=20
like a large drawback. I would rather see an attribute that tells the=20
compiler that this member does not need to be a complete sub-object (it can=
=20
have the same address as an object of a different type, just like for the=
=20
empty base optimization), as in=20
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D63579 . At some point we cou=
ld=20
even consider making it the default: I only ever heard once of a piece of=
=20
code this would break, while I keep seeing classes that empty members are=
=20
making unnecessarily large.

--=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_2499_914247148.1426417262741
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Le dimanche 15 mars 2015 10:38:52 UTC+1, andrew....@gmail.=
com a =C3=A9crit&nbsp;:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr">Right now there is no good way to conditionally include member va=
riable into a structure definition. This ability is important, for example,=
 to avoid allocating space for empty members and thus bloating structure si=
ze (example: generic container with user-defined allocator; allocator is of=
ten an empty structure).<br><br>Motivating example 1 - container with alloc=
ator:<br>template&lt;typename T, typename Al&gt; struct my_container {<br>&=
nbsp; T *data;<br>&nbsp; Al alloc; // bloats structure size unnecessarily i=
f allocator is empty!<br>};<br>static_assert(sizeof(my_<wbr>container&lt;in=
t, my_stateless_alloc&gt;) &gt; sizeof(int*), "");<br><br>Motivating exampl=
e 2 - serialized messages:<br>enum message_type { MT_INT, MT_EMPTY };<br>st=
ruct message_header { message_type t; };<br><br>template&lt;message_type Ty=
pe&gt; struct message_payload;<br>template&lt;&gt; struct message_payload&l=
t;MT_INT&gt;&nbsp;&nbsp; { int data; };<br>template&lt;&gt; struct message_=
payload&lt;MT_EMPTY&gt; {};<br><br>template&lt;message_type Type&gt; struct=
 message {<br>&nbsp; message_header header;<br>&nbsp; message_payload&lt;Ty=
pe&gt; payload; // wastes space for empty payloads!<br>};<br>static_assert(=
sizeof(message&lt;<wbr>MT_EMPTY&gt;) &gt; sizeof(message_header), "");<br><=
br>Currently used workarounds are based on supplemental template structure =
with dispatch based on is_empty&lt;&gt; result. Examples above are rewritte=
n as:<br>template&lt;bool IsEmpty, typename Al&gt; struct my_container_base=
 { Al al; };<br>template&lt;typename Al&gt; struct my_container_base &lt; t=
rue, Al &gt; {};<br>template&lt;typename T, typename Al&gt; struct my_conta=
iner : public my_container_base&lt;std::is_<wbr>empty&lt;Al&gt;::value, Al&=
gt; {<br>&nbsp; T* data; // useful data is now offset from the beginning of=
 my_container structure; in general case it could be undesired - for exampl=
e, it could make us touch an extra cache line on fast path in some cases<br=
>};<br><br>template&lt;bool IsEmpty, typename Payload&gt; struct message_im=
pl {<br>&nbsp; message_header header;<br>&nbsp; Payload payload;<br>};<br>t=
emplate&lt;typename Payload&gt; struct message_impl&lt;true, Payload&gt; {<=
br>&nbsp; message_header header; // here order is really important, so inhe=
ritance/empty-base-class-<wbr>optimization can't be used; we have to write =
same things twice<br>};<br>template&lt;message_type Type&gt; struct message=
 : public message_impl&lt;std::is_empty&lt;<wbr>message_payload&lt;Type&gt;=
&gt;::value, message_payload&lt;Type&gt;&gt; {};<br><br>This workaround sca=
les poorly if there are several potentially empty template parameters.<br><=
br>The proposal is to add a construct (member variable with type "void") th=
at would essentially be skipped by the compiler without affecting structure=
 layout. Accessing such member variable (value or address) would be a compi=
le-time error. Then code pieces above could be rewritten like this:<br>temp=
late&lt;typename T&gt; using nonempty_only =3D std::conditional_t&lt;std::i=
s_<wbr>empty&lt;T&gt;::value, void, T&gt;;<br>template&lt;typename T, typen=
ame Al&gt; struct my_container {<br>&nbsp; T *data;<br>&nbsp; nonempty_only=
&lt;Al&gt; alloc; // won't affect layout if Al is empty<br>};<br>template&l=
t;message_type Type&gt; struct message {<br>&nbsp; message_header header;<b=
r>&nbsp; nonempty_only&lt;message_payload&lt;<wbr>Type&gt;&gt; payload;<br>=
};<br></div></blockquote><div><br>Not being able to use the empty member (c=
all its member functions) looks like a large drawback. I would rather see a=
n attribute that tells the compiler that this member does not need to be a =
complete sub-object (it can have the same address as an object of a differe=
nt type, just like for the empty base optimization), as in https://gcc.gnu.=
org/bugzilla/show_bug.cgi?id=3D63579 . At some point we could even consider=
 making it the default: I only ever heard once of a piece of code this woul=
d break, while I keep seeing classes that empty members are making unnecess=
arily large.<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_2499_914247148.1426417262741--
------=_Part_2498_166031743.1426417262741--

.


Author: David Krauss <potswa@gmail.com>
Date: Sun, 15 Mar 2015 20:50:28 +0800
Raw View
--Apple-Mail=_77BD0BDA-386E-4E05-9B2D-42EC81F1439B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8



> On 2015=E2=80=9303=E2=80=9315, at 5:38 PM, andrew.gilewsky@gmail.com wrot=
e:
>=20
>   T* data; // useful data is now offset from the beginning of my_containe=
r structure; in general case it could be undesired - for example, it could =
make us touch an extra cache line on fast path in some cases

Base classes don=E2=80=99t seem to have any technical disadvantages. Even i=
f you=E2=80=99re trying to fine-tune the memory layout, you can move member=
s before the optional one into another base class.

They=E2=80=99re unintuitive, though. Perhaps requires clauses from Concepts=
 can be made applicable to data members.

I don=E2=80=99t like the idea of reserving a name to a member that=E2=80=99=
s not accessible anywhere, though. Or seeming to have an object of incomple=
te type, even if it=E2=80=99s =E2=80=9Conly=E2=80=9D void.

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

--Apple-Mail=_77BD0BDA-386E-4E05-9B2D-42EC81F1439B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><div><br class=3D""></div><div><blockquote type=3D"cite" class=3D""><div =
class=3D"">On 2015=E2=80=9303=E2=80=9315, at 5:38 PM, <a href=3D"mailto:and=
rew.gilewsky@gmail.com" class=3D"">andrew.gilewsky@gmail.com</a> wrote:</di=
v><br class=3D"Apple-interchange-newline"><div class=3D""><span class=3D"" =
style=3D"float: none; display: inline !important;">&nbsp; T* data; // usefu=
l data is now offset from the beginning of my_container structure; in gener=
al case it could be undesired - for example, it could make us touch an extr=
a cache line on fast path in some cases</span></div></blockquote><br class=
=3D""></div><div>Base classes don=E2=80=99t seem to have any technical disa=
dvantages. Even if you=E2=80=99re trying to fine-tune the memory layout, yo=
u can move members before the optional one into another base class.</div><d=
iv><br class=3D""></div><div>They=E2=80=99re unintuitive, though. Perhaps r=
equires clauses from Concepts can be made applicable to data members.</div>=
<div><br class=3D""></div><div>I don=E2=80=99t like the idea of reserving a=
 name to a member that=E2=80=99s not accessible anywhere, though. Or seemin=
g to have an object of incomplete type, even if it=E2=80=99s =E2=80=9Conly=
=E2=80=9D <font face=3D"Courier" class=3D"">void</font>.</div></div></body>=
</html>

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

--Apple-Mail=_77BD0BDA-386E-4E05-9B2D-42EC81F1439B--

.


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Sun, 15 Mar 2015 23:17:18 -0700 (PDT)
Raw View
------=_Part_1570_922778060.1426486638331
Content-Type: text/plain; charset=UTF-8

Another reason to allow void members is to avoid having to specialize templates for void. Note that this is allowed for this reason:

void f();

void g()
{
   return f();
}

--

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

.


Author: David Krauss <potswa@gmail.com>
Date: Mon, 16 Mar 2015 14:24:52 +0800
Raw View
> On 2015=E2=80=9303=E2=80=9316, at 2:17 PM, Bengt Gustafsson <bengt.gustaf=
sson@beamways.com> wrote:
>=20
> Another reason to allow void members is to avoid having to specialize tem=
plates for void. Note that this is allowed for this reason:

That =E2=80=9Cfeature=E2=80=9D is way older than templates.

--=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: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Mon, 16 Mar 2015 20:29:55 -0700 (PDT)
Raw View
------=_Part_47_1250335918.1426562995784
Content-Type: multipart/alternative;
 boundary="----=_Part_48_1268287931.1426562995784"

------=_Part_48_1268287931.1426562995784
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Sunday, March 15, 2015 at 4:01:02 AM UTC-7, Marc wrote:
>
> Le dimanche 15 mars 2015 10:38:52 UTC+1, andrew....@gmail.com a =C3=A9cri=
t :
>>
>> Right now there is no good way to conditionally include member variable=
=20
>> into a structure definition. This ability is important, for example, to=
=20
>> avoid allocating space for empty members and thus bloating structure siz=
e=20
>> (example: generic container with user-defined allocator; allocator is of=
ten=20
>> an empty structure).
>>
>> Motivating example 1 - container with allocator:
>> template<typename T, typename Al> struct my_container {
>>   T *data;
>>   Al alloc; // bloats structure size unnecessarily if allocator is empty=
!
>> };
>> static_assert(sizeof(my_container<int, my_stateless_alloc>) >=20
>> sizeof(int*), "");
>>
>
....Because under the current rules, even if Al is an empty struct,=20
&myarray[42].alloc must be a unique address distinct from &myarray[43].data=
..
It took me a while to remember that, so I mention it here for posterity. :)
=20

> Currently used workarounds are based on supplemental template structure=
=20
>> with dispatch based on is_empty<> result. Examples above are rewritten a=
s:
>> template<bool IsEmpty, typename Al> struct my_container_base { Al al; };
>> template<typename Al> struct my_container_base < true, Al > {};
>> template<typename T, typename Al> struct my_container : public=20
>> my_container_base<std::is_empty<Al>::value, Al> {
>>   T* data; // useful data is now offset from the beginning of=20
>> my_container structure; in general case it could be undesired - for=20
>> example, it could make us touch an extra cache line on fast path in some=
=20
>> cases
>> };
>>
>> template<bool IsEmpty, typename Payload> struct message_impl {
>>   message_header header;
>>   Payload payload;
>> };
>> template<typename Payload> struct message_impl<true, Payload> {
>>   message_header header; // here order is really important, so=20
>> inheritance/empty-base-class-optimization can't be used; we have to writ=
e=20
>> same things twice
>> };
>> template<message_type Type> struct message : public=20
>> message_impl<std::is_empty<message_payload<Type>>::value,=20
>> message_payload<Type>> {};
>>
>> This workaround scales poorly if there are several potentially empty=20
>> template parameters.
>>
>> The proposal is to add a construct (member variable with type "void")=20
>> that would essentially be skipped by the compiler without affecting=20
>> structure layout. Accessing such member variable (value or address) woul=
d=20
>> be a compile-time error. Then code pieces above could be rewritten like=
=20
>> this:
>> template<typename T> using nonempty_only =3D=20
>> std::conditional_t<std::is_empty<T>::value, void, T>;
>> template<typename T, typename Al> struct my_container {
>>   T *data;
>>   nonempty_only<Al> alloc; // won't affect layout if Al is empty
>> };
>> template<message_type Type> struct message {
>>   message_header header;
>>   nonempty_only<message_payload<Type>> payload;
>> };
>>
>
> Not being able to use the empty member (call its member functions) looks=
=20
> like a large drawback. I would rather see an attribute that tells the=20
> compiler that this member does not need to be a complete sub-object (it c=
an=20
> have the same address as an object of a different type, just like for the=
=20
> empty base optimization), as in=20
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D63579 . At some point we=
=20
> could even consider making it the default: I only ever heard once of a=20
> piece of code this would break, while I keep seeing classes that empty=20
> members are making unnecessarily large.
>

I like both ideas (allowing "non-padding" NSDMs and adding a standard=20
[[gnu::empty]] or [[nonpadding]] attribute), but I don't like the idea of=
=20
"overloading" void with this extra meaning.

IMHO, this situation is analogous to the situation with std::less<>: when=
=20
confronted with the need for a special "flag" type meaning "Do What I=20
Mean", the Committee IMHO misstepped by overloading void with that meaning=
=20
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421.htm> (making=
=20
std::less<> a synonym for std::less<void>) instead of inventing a new flag=
=20
type struct generic_comparator_t{} (and making std::less<> a synonym for=20
std::less<std::generic_comparator_t>). We can see from the currently=20
running thread on "postfix increment/decrement operators" that overloading=
=20
built-in types with weird and non-obvious meanings is never a good idea in=
=20
hindsight. :)

The solution is analogous too: If there's no consensus to add a=20
[[nonpadding]] attribute (or to make non-padding-ness the default for every=
=20
empty member, as it currently is for empty base classes), then we could add=
=20
a single library type std::empty_t that alone is guaranteed to have the=20
behavior. This could be implemented by compiler magic, or by

    namespace std {
        struct [[gnu::empty]] empty_t {};
    }

or by some other means (I don't know what).  All your examples continue to=
=20
work perfectly, except that you'd replace void with empty_t, which is=20
arguably more self-documenting anyway.

A completely separate alternative would be to work out a complete proposal=
=20
for making "bit-field types" first-class citizens of C++, and then making=
=20
std::empty_t a synonym for char:0. (But my impression is that the attempt=
=20
would be thankless and probably fruitless.)

my $.02,
Arthur

--=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_48_1268287931.1426562995784
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Sunday, March 15, 2015 at 4:01:02 AM UTC-7, Marc wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Le dimanche 1=
5 mars 2015 10:38:52 UTC+1, <a>andrew....@gmail.com</a> a =C3=A9crit&nbsp;:=
<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">Right now there is=
 no good way to conditionally include member variable into a structure defi=
nition. This ability is important, for example, to avoid allocating space f=
or empty members and thus bloating structure size (example: generic contain=
er with user-defined allocator; allocator is often an empty structure).<br>=
<br>Motivating example 1 - container with allocator:<br>template&lt;typenam=
e T, typename Al&gt; struct my_container {<br>&nbsp; T *data;<br>&nbsp; Al =
alloc; // bloats structure size unnecessarily if allocator is empty!<br>};<=
br>static_assert(sizeof(my_<wbr>container&lt;int, my_stateless_alloc&gt;) &=
gt; sizeof(int*), "");<br></div></blockquote></div></blockquote><div><br></=
div><div>...Because under the current rules, even if <font face=3D"courier =
new, monospace">Al</font> is an empty struct,&nbsp;<font face=3D"courier ne=
w, monospace">&amp;myarray[42].alloc</font> must be a unique address distin=
ct from <font face=3D"courier new, monospace">&amp;myarray[43].data</font>.=
</div><div>It took me a while to remember that, so I mention it here for po=
sterity. :)</div><div>&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"><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">Currently used workarounds are based on supplemental template structur=
e with dispatch based on is_empty&lt;&gt; result. Examples above are rewrit=
ten as:<br>template&lt;bool IsEmpty, typename Al&gt; struct my_container_ba=
se { Al al; };<br>template&lt;typename Al&gt; struct my_container_base &lt;=
 true, Al &gt; {};<br>template&lt;typename T, typename Al&gt; struct my_con=
tainer : public my_container_base&lt;std::is_<wbr>empty&lt;Al&gt;::value, A=
l&gt; {<br>&nbsp; T* data; // useful data is now offset from the beginning =
of my_container structure; in general case it could be undesired - for exam=
ple, it could make us touch an extra cache line on fast path in some cases<=
br>};<br><br>template&lt;bool IsEmpty, typename Payload&gt; struct message_=
impl {<br>&nbsp; message_header header;<br>&nbsp; Payload payload;<br>};<br=
>template&lt;typename Payload&gt; struct message_impl&lt;true, Payload&gt; =
{<br>&nbsp; message_header header; // here order is really important, so in=
heritance/empty-base-class-<wbr>optimization can't be used; we have to writ=
e same things twice<br>};<br>template&lt;message_type Type&gt; struct messa=
ge : public message_impl&lt;std::is_empty&lt;<wbr>message_payload&lt;Type&g=
t;&gt;::value, message_payload&lt;Type&gt;&gt; {};<br><br>This workaround s=
cales poorly if there are several potentially empty template parameters.<br=
><br>The proposal is to add a construct (member variable with type "void") =
that would essentially be skipped by the compiler without affecting structu=
re layout. Accessing such member variable (value or address) would be a com=
pile-time error. Then code pieces above could be rewritten like this:<br>te=
mplate&lt;typename T&gt; using nonempty_only =3D std::conditional_t&lt;std:=
:is_<wbr>empty&lt;T&gt;::value, void, T&gt;;<br>template&lt;typename T, typ=
ename Al&gt; struct my_container {<br>&nbsp; T *data;<br>&nbsp; nonempty_on=
ly&lt;Al&gt; alloc; // won't affect layout if Al is empty<br>};<br>template=
&lt;message_type Type&gt; struct message {<br>&nbsp; message_header header;=
<br>&nbsp; nonempty_only&lt;message_payload&lt;<wbr>Type&gt;&gt; payload;<b=
r>};<br></div></blockquote><div><br>Not being able to use the empty member =
(call its member functions) looks like a large drawback. I would rather see=
 an attribute that tells the compiler that this member does not need to be =
a complete sub-object (it can have the same address as an object of a diffe=
rent type, just like for the empty base optimization), as in <a href=3D"htt=
ps://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D63579" target=3D"_blank" rel=3D=
"nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url?q\75https=
%3A%2F%2Fgcc.gnu.org%2Fbugzilla%2Fshow_bug.cgi%3Fid%3D63579\46sa\75D\46sntz=
\0751\46usg\75AFQjCNFV2vVCeERF0jdNdw7OCcc6kSoOZg';return true;" onclick=3D"=
this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fgcc.gnu.org%2Fbug=
zilla%2Fshow_bug.cgi%3Fid%3D63579\46sa\75D\46sntz\0751\46usg\75AFQjCNFV2vVC=
eERF0jdNdw7OCcc6kSoOZg';return true;">https://gcc.gnu.org/bugzilla/<wbr>sho=
w_bug.cgi?id=3D63579</a> . At some point we could even consider making it t=
he default: I only ever heard once of a piece of code this would break, whi=
le I keep seeing classes that empty members are making unnecessarily large.=
<br></div></div></blockquote><div><br></div><div>I like both ideas (allowin=
g "non-padding" NSDMs and adding a standard <font face=3D"courier new, mono=
space">[[gnu::empty]]</font> or <font face=3D"courier new, monospace">[[non=
padding]]</font> attribute), but I don't like the idea of "overloading" <fo=
nt face=3D"courier new, monospace">void</font> with this extra meaning.</di=
v><div><br></div><div>IMHO, this situation is analogous to the situation wi=
th <font face=3D"courier new, monospace">std::less&lt;&gt;</font>: when con=
fronted with the need for a special "flag" type meaning "Do What I Mean", t=
he Committee IMHO misstepped by <a href=3D"http://www.open-std.org/jtc1/sc2=
2/wg21/docs/papers/2012/n3421.htm">overloading <font face=3D"courier new, m=
onospace">void</font> with that meaning</a>&nbsp;(making <font face=3D"cour=
ier new, monospace">std::less&lt;&gt;</font> a synonym for <font face=3D"co=
urier new, monospace">std::less&lt;void&gt;</font>) instead of inventing a =
new flag type <font face=3D"courier new, monospace">struct generic_comparat=
or_t{}</font> (and making <font face=3D"courier new, monospace">std::less&l=
t;&gt;</font> a synonym for <font face=3D"courier new, monospace">std::less=
&lt;std::generic_comparator_t&gt;</font>). We can see from the currently ru=
nning thread on "postfix increment/decrement operators" that overloading bu=
ilt-in types with weird and non-obvious meanings is never a good idea in hi=
ndsight. :)</div><div><br></div><div>The solution is analogous too: If ther=
e's no consensus to add a <font face=3D"courier new, monospace">[[nonpaddin=
g]]</font> attribute (or to make non-padding-ness the default for every emp=
ty member, as it currently is for empty base classes), then we could add a =
single library type <font face=3D"courier new, monospace">std::empty_t</fon=
t> that alone is guaranteed to have the behavior. This could be implemented=
 by compiler magic, or by</div><div><br></div><div><font face=3D"courier ne=
w, monospace">&nbsp; &nbsp; namespace std {</font></div><div><font face=3D"=
courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; struct [[gnu::empty]] e=
mpty_t {};</font></div><div><font face=3D"courier new, monospace">&nbsp; &n=
bsp; }</font></div><div><br></div><div>or by some other means (I don't know=
 what). &nbsp;All your examples continue to work perfectly, except that you=
'd replace <font face=3D"courier new, monospace">void</font> with <font fac=
e=3D"courier new, monospace">empty_t</font>, which is arguably more self-do=
cumenting anyway.</div><div><br></div><div>A completely separate alternativ=
e would be to work out a complete proposal for making "bit-field types" fir=
st-class citizens of C++, and then making <font face=3D"courier new, monosp=
ace">std::empty_t</font> a synonym for <font face=3D"courier new, monospace=
">char:0</font>. (But my impression is that the attempt would be thankless =
and probably fruitless.)</div><div><br></div><div>my $.02,</div><div>Arthur=
</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_48_1268287931.1426562995784--
------=_Part_47_1250335918.1426562995784--

.


Author: David Krauss <potswa@gmail.com>
Date: Tue, 17 Mar 2015 18:24:42 +0800
Raw View
--Apple-Mail=_F2536C4C-BAE1-4136-B41D-58F9F98276CC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8

By the way, there=E2=80=99s already something very close to void member var=
iables: Use a non-function declarator to declare a member function.

template< typename t >
struct s {
    std::conditional_t< predicate_v< t >, t, void() > mem;
};

If this is allowed, and you=E2=80=99re really, truly not using the member i=
n specializations where it shouldn=E2=80=99t exist, it will work. Otherwise=
, you=E2=80=99ll get (at least) a link error.

The implementations I checked all reject this, specifically citing the tric=
k as illegal, but I can=E2=80=99t find where the standard prohibits it, at =
least in [temp.inst] or [temp.class]. Perhaps it=E2=80=99s in a longstandin=
g DR? If so, and CWG can be convinced to revisit it, the feature might be c=
onsidered not an extension.


> On 2015=E2=80=9303=E2=80=9317, at 11:29 AM, Arthur O'Dwyer <arthur.j.odwy=
er@gmail.com> wrote:
>=20
> This could be implemented by compiler magic, or by
>=20
>     namespace std {
>         struct [[gnu::empty]] empty_t {};
>     }
>=20
> or by some other means (I don't know what).=20

This is only half a solution, since empty base classes can provide function=
ality even while taking no space.

Modifying it slightly, consider a template which applies the magic:

// Derive from non-empty bases and provide access through function call ope=
rator.
template< typename base, typename =3D void >
struct [[gnu::non_padding]] unpadded_value
    : base {
    using base::base;
    unpadded_value( base const & b ) : base( b ) {}
    unpadded_value( base && b ) : base( std::move( b ) ) {}
};

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

--Apple-Mail=_F2536C4C-BAE1-4136-B41D-58F9F98276CC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D"">By=
 the way, there=E2=80=99s already something very close to void member varia=
bles: Use a non-function declarator to declare a member function.</div><div=
 class=3D""><br class=3D""></div><div class=3D""><font face=3D"Courier" cla=
ss=3D"">template&lt; typename t &gt;</font></div><div class=3D""><font face=
=3D"Courier" class=3D"">struct s {</font></div><div class=3D""><font face=
=3D"Courier" class=3D"">&nbsp; &nbsp; std::conditional_t&lt; predicate_v&lt=
; t &gt;, t, void() &gt; mem;</font></div><div class=3D""><font face=3D"Cou=
rier" class=3D"">};</font></div><div class=3D""><br class=3D""></div><div c=
lass=3D"">If this is allowed, and you=E2=80=99re really, truly not using th=
e member in specializations where it shouldn=E2=80=99t exist, it will work.=
 Otherwise, you=E2=80=99ll get (at least) a link error.</div><div class=3D"=
"><br class=3D""></div><div class=3D"">The implementations I checked all re=
ject this, specifically citing the trick as illegal, but I can=E2=80=99t fi=
nd where the standard prohibits it, at least in [temp.inst] or [temp.class]=
.. Perhaps it=E2=80=99s in a longstanding DR? If so, and CWG can be convince=
d to revisit it, the feature might be considered not an extension.</div><di=
v class=3D""><br class=3D""></div><br class=3D""><div><blockquote type=3D"c=
ite" class=3D""><div class=3D"">On 2015=E2=80=9303=E2=80=9317, at 11:29 AM,=
 Arthur O'Dwyer &lt;<a href=3D"mailto:arthur.j.odwyer@gmail.com" class=3D""=
>arthur.j.odwyer@gmail.com</a>&gt; wrote:</div><br class=3D"Apple-interchan=
ge-newline"><div class=3D""><div style=3D"font-family: Helvetica; font-size=
: 12px; font-style: normal; font-variant: normal; font-weight: normal; lett=
er-spacing: normal; line-height: normal; orphans: auto; text-align: start; =
text-indent: 0px; text-transform: none; white-space: normal; widows: auto; =
word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D"">This could b=
e implemented by compiler magic, or by</div><div style=3D"font-family: Helv=
etica; font-size: 12px; font-style: normal; font-variant: normal; font-weig=
ht: normal; letter-spacing: normal; line-height: normal; orphans: auto; tex=
t-align: start; text-indent: 0px; text-transform: none; white-space: normal=
; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=
=3D""><br class=3D""></div><div style=3D"font-family: Helvetica; font-size:=
 12px; font-style: normal; font-variant: normal; font-weight: normal; lette=
r-spacing: normal; line-height: normal; orphans: auto; text-align: start; t=
ext-indent: 0px; text-transform: none; white-space: normal; widows: auto; w=
ord-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><font face=3D=
"courier new, monospace" class=3D"">&nbsp; &nbsp; namespace std {</font></d=
iv><div style=3D"font-family: Helvetica; font-size: 12px; font-style: norma=
l; font-variant: normal; font-weight: normal; letter-spacing: normal; line-=
height: normal; orphans: auto; text-align: start; text-indent: 0px; text-tr=
ansform: none; white-space: normal; widows: auto; word-spacing: 0px; -webki=
t-text-stroke-width: 0px;" class=3D""><font face=3D"courier new, monospace"=
 class=3D"">&nbsp; &nbsp; &nbsp; &nbsp; struct [[gnu::empty]] empty_t {};</=
font></div><div style=3D"font-family: Helvetica; font-size: 12px; font-styl=
e: normal; font-variant: normal; font-weight: normal; letter-spacing: norma=
l; line-height: normal; orphans: auto; text-align: start; text-indent: 0px;=
 text-transform: none; white-space: normal; widows: auto; word-spacing: 0px=
; -webkit-text-stroke-width: 0px;" class=3D""><font face=3D"courier new, mo=
nospace" class=3D"">&nbsp; &nbsp; }</font></div><div style=3D"font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-=
weight: normal; letter-spacing: normal; line-height: normal; orphans: auto;=
 text-align: start; text-indent: 0px; text-transform: none; white-space: no=
rmal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" cla=
ss=3D""><br class=3D""></div><div style=3D"font-family: Helvetica; font-siz=
e: 12px; font-style: normal; font-variant: normal; font-weight: normal; let=
ter-spacing: normal; line-height: normal; orphans: auto; text-align: start;=
 text-indent: 0px; text-transform: none; white-space: normal; widows: auto;=
 word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D"">or by some =
other means (I don't know what).<span class=3D"Apple-converted-space">&nbsp=
;</span></div></div></blockquote></div><br class=3D""><div class=3D"">This =
is only half a solution, since empty base classes can provide functionality=
 even while taking no space.</div><div class=3D""><br class=3D""></div><div=
 class=3D"">Modifying it slightly, consider a template which applies the ma=
gic:</div><div class=3D""><br class=3D""></div><div class=3D""><font face=
=3D"Courier" class=3D"">// Derive from non-empty bases and provide access t=
hrough function call operator.</font></div><div class=3D""><font face=3D"Co=
urier" class=3D"">template&lt; typename base, typename =3D void &gt;</font>=
</div><div class=3D""><font face=3D"Courier" class=3D"">struct [[gnu::non_p=
adding]] unpadded_value</font></div><div class=3D""><font face=3D"Courier" =
class=3D"">&nbsp; &nbsp; : base {</font></div><div class=3D""><font face=3D=
"Courier" class=3D"">&nbsp; &nbsp; using base::base;</font></div><div class=
=3D""><font face=3D"Courier" class=3D"">&nbsp; &nbsp; unpadded_value( base =
const &amp; b ) : base( b ) {}</font></div><div class=3D""><font face=3D"Co=
urier" class=3D"">&nbsp; &nbsp; unpadded_value( base &amp;&amp; b ) : base(=
 std::move( b ) ) {}</font></div><div class=3D""><font face=3D"Courier" cla=
ss=3D"">};</font></div></body></html>

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

--Apple-Mail=_F2536C4C-BAE1-4136-B41D-58F9F98276CC--

.


Author: andrew.gilewsky@gmail.com
Date: Tue, 17 Mar 2015 11:27:22 -0700 (PDT)
Raw View
------=_Part_2081_873055568.1426616842120
Content-Type: multipart/alternative;
 boundary="----=_Part_2082_1836655072.1426616842120"

------=_Part_2082_1836655072.1426616842120
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Tuesday, March 17, 2015 at 3:04:06 PM UTC+3, David Krauss wrote:
>
> By the way, there=E2=80=99s already something very close to void member v=
ariables:=20
> Use a non-function declarator to declare a member function
>
Interesting. If it really doesn't contradict anything in the standard, then=
=20
that's a solution I suppose.

Regarding [[empty]] attribute - that's an alternative, of course, however I=
=20
was under impression that attributes are really intended to be used as=20
compiler-specific extensions or optional hints (i.e. compiler is basically=
=20
free to ignore them). In this case I'd rather have compiler not supporting=
=20
the feature give me an error than change memory layout of structures=20
silently.

I don't think it is really viable to propose "empty member takes zero=20
space" approach suggested above (would change meaning of a lot of existing=
=20
code) or adding magic std::empty_t (as far as I understand, no one wants=20
compiler to treat 'std' namespace members in a special way).

BTW I think following (mentioned earlier in the thread) is a very good=20
point:
>> Another reason to allow void members is to avoid having to specialize=20
templates for void.

--=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_2082_1836655072.1426616842120
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, March 17, 2015 at 3:04:06 PM UTC+3, David Krau=
ss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wr=
ap:break-word"><div>By the way, there=E2=80=99s already something very clos=
e to void member variables: Use a non-function declarator to declare a memb=
er function</div></div></blockquote><div>Interesting. If it really doesn't =
contradict anything in the standard, then that's a solution I suppose.<br><=
br>Regarding [[empty]] attribute - that's an alternative, of course, howeve=
r I was under impression that attributes are really intended to be used as =
compiler-specific extensions or optional hints (i.e. compiler is basically =
free to ignore them). In this case I'd rather have compiler not supporting =
the feature give me an error than change memory layout of structures silent=
ly.<br><br>I don't think it is really viable to propose "empty member takes=
 zero space" approach suggested above (would change meaning of a lot of exi=
sting code) or adding magic std::empty_t (as far as I understand, no one wa=
nts compiler to treat 'std' namespace members in a special way).<br><br>BTW=
 I think following (mentioned earlier in the thread) is a very good point:<=
br>&gt;&gt; Another reason to allow void members is to avoid having to spec=
ialize templates for void.<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_2082_1836655072.1426616842120--
------=_Part_2081_873055568.1426616842120--

.


Author: David Krauss <potswa@gmail.com>
Date: Wed, 18 Mar 2015 09:21:07 +0800
Raw View
--Apple-Mail=_815943B6-9DDF-4D5A-BC70-5AAE8EB958CA
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2015=E2=80=9303=E2=80=9318, at 2:27 AM, andrew.gilewsky@gmail.com wrot=
e:
>=20
> On Tuesday, March 17, 2015 at 3:04:06 PM UTC+3, David Krauss wrote:
> By the way, there=E2=80=99s already something very close to void member v=
ariables: Use a non-function declarator to declare a member function
> Interesting. If it really doesn't contradict anything in the standard, th=
en that's a solution I suppose.

I=E2=80=99ve asked SO: http://stackoverflow.com/q/29112567/153285

> Regarding [[empty]] attribute - that's an alternative, of course, however=
 I was under impression that attributes are really intended to be used as c=
ompiler-specific extensions or optional hints (i.e. compiler is basically f=
ree to ignore them). In this case I'd rather have compiler not supporting t=
he feature give me an error than change memory layout of structures silentl=
y.

It depends whether the attribute becomes part of the ABI. I don=E2=80=99t s=
uppose there=E2=80=99s a precedent for this, but attributes being optional =
(and merely =E2=80=9Csemantic comments=E2=80=9D) in terms of the standard d=
oesn=E2=80=99t mean they can=E2=80=99t be more to the ABI.

> (as far as I understand, no one wants compiler to treat 'std' namespace m=
embers in a special way).

Special library hooks are actually preferred to core language extensions, i=
n general: The impact on the standard is less. However, std::empty_t alone =
isn=E2=80=99t as expressive as the the attribute or the empty base class op=
timization.

> BTW I think following (mentioned earlier in the thread) is a very good po=
int:
> >> Another reason to allow void members is to avoid having to specialize =
templates for void.

What=E2=80=99s the use case? A void member cannot be accessed at all, at le=
ast without significant further extensions to the language. You only avoid =
the need for further specialization when the implicit instantiations won=E2=
=80=99t ever use that member.

Perhaps it=E2=80=99s useful for dumb container templates, but that suggests=
 the template is either poorly designed or so generic (e.g. std::tuple) tha=
t the EBCO is applicable.

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

--Apple-Mail=_815943B6-9DDF-4D5A-BC70-5AAE8EB958CA
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9303=
=E2=80=9318, at 2:27 AM, <a href=3D"mailto:andrew.gilewsky@gmail.com" class=
=3D"">andrew.gilewsky@gmail.com</a> wrote:</div><br class=3D"Apple-intercha=
nge-newline"><div class=3D""><div dir=3D"ltr" class=3D"">On Tuesday, March =
17, 2015 at 3:04:06 PM UTC+3, David Krauss wrote:<blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div style=3D"word-wrap:break-word" class=3D""><div clas=
s=3D"">By the way, there=E2=80=99s already something very close to void mem=
ber variables: Use a non-function declarator to declare a member function</=
div></div></blockquote><div class=3D"">Interesting. If it really doesn't co=
ntradict anything in the standard, then that's a solution I suppose.<br cla=
ss=3D""></div></div></div></blockquote><div><br class=3D""></div>I=E2=80=99=
ve asked SO: <a href=3D"http://stackoverflow.com/q/29112567/153285" class=
=3D"">http://stackoverflow.com/q/29112567/153285</a></div><div><br class=3D=
""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" cl=
ass=3D""><div class=3D"">Regarding [[empty]] attribute - that's an alternat=
ive, of course, however I was under impression that attributes are really i=
ntended to be used as compiler-specific extensions or optional hints (i.e. =
compiler is basically free to ignore them). In this case I'd rather have co=
mpiler not supporting the feature give me an error than change memory layou=
t of structures silently.<br class=3D""></div></div></div></blockquote><div=
><br class=3D""></div><div>It depends whether the attribute becomes part of=
 the ABI. I don=E2=80=99t suppose there=E2=80=99s a precedent for this, but=
 attributes being optional (and merely =E2=80=9Csemantic comments=E2=80=9D)=
 in terms of the standard doesn=E2=80=99t mean they can=E2=80=99t be more t=
o the ABI.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div cl=
ass=3D""><div dir=3D"ltr" class=3D""><div class=3D"">(as far as I understan=
d, no one wants compiler to treat 'std' namespace members in a special way)=
..<br class=3D""></div></div></div></blockquote><div><br class=3D""></div><d=
iv>Special library hooks are actually preferred to core language extensions=
, in general: The impact on the standard is less. However, <font face=3D"Co=
urier" class=3D"">std::empty_t</font>&nbsp;alone isn=E2=80=99t as expressiv=
e as the the attribute or the empty base class optimization.</div><br class=
=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr"=
 class=3D""><div class=3D"">BTW I think following (mentioned earlier in the=
 thread) is a very good point:<br class=3D"">&gt;&gt; Another reason to all=
ow void members is to avoid having to specialize templates for void.</div><=
/div></div></blockquote><br class=3D""></div><div>What=E2=80=99s the use ca=
se? A void member cannot be accessed at all, at least without significant f=
urther extensions to the language. You only avoid the need for further spec=
ialization when the implicit instantiations won=E2=80=99t ever use that mem=
ber.</div><div><br class=3D""></div><div>Perhaps it=E2=80=99s useful for du=
mb container templates, but that suggests the template is either poorly des=
igned or so generic (e.g. <font face=3D"Courier" class=3D"">std::tuple</fon=
t>) that the EBCO is applicable.</div></body></html>

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

--Apple-Mail=_815943B6-9DDF-4D5A-BC70-5AAE8EB958CA--

.


Author: Douglas Boffey <douglas.boffey@gmail.com>
Date: Wed, 18 Mar 2015 02:52:35 +0000
Raw View
Excuse my ignorance, but what is EBCO?

On 3/18/15, David Krauss <potswa@gmail.com> wrote:
>
>> On 2015=E2=80=9303=E2=80=9318, at 2:27 AM, andrew.gilewsky@gmail.com wro=
te:
>>
>> On Tuesday, March 17, 2015 at 3:04:06 PM UTC+3, David Krauss wrote:
>> By the way, there=E2=80=99s already something very close to void member =
variables:
>> Use a non-function declarator to declare a member function
>> Interesting. If it really doesn't contradict anything in the standard,
>> then that's a solution I suppose.
>
> I=E2=80=99ve asked SO: http://stackoverflow.com/q/29112567/153285
>
>> Regarding [[empty]] attribute - that's an alternative, of course, howeve=
r
>> I was under impression that attributes are really intended to be used as
>> compiler-specific extensions or optional hints (i.e. compiler is basical=
ly
>> free to ignore them). In this case I'd rather have compiler not supporti=
ng
>> the feature give me an error than change memory layout of structures
>> silently.
>
> It depends whether the attribute becomes part of the ABI. I don=E2=80=99t=
 suppose
> there=E2=80=99s a precedent for this, but attributes being optional (and =
merely
> =E2=80=9Csemantic comments=E2=80=9D) in terms of the standard doesn=E2=80=
=99t mean they can=E2=80=99t be
> more to the ABI.
>
>> (as far as I understand, no one wants compiler to treat 'std' namespace
>> members in a special way).
>
> Special library hooks are actually preferred to core language extensions,=
 in
> general: The impact on the standard is less. However, std::empty_t alone
> isn=E2=80=99t as expressive as the the attribute or the empty base class
> optimization.
>
>> BTW I think following (mentioned earlier in the thread) is a very good
>> point:
>> >> Another reason to allow void members is to avoid having to specialize
>> >> templates for void.
>
> What=E2=80=99s the use case? A void member cannot be accessed at all, at =
least
> without significant further extensions to the language. You only avoid th=
e
> need for further specialization when the implicit instantiations won=E2=
=80=99t ever
> use that member.
>
> Perhaps it=E2=80=99s useful for dumb container templates, but that sugges=
ts the
> template is either poorly designed or so generic (e.g. std::tuple) that t=
he
> EBCO is applicable.
>
> --
>
> ---
> 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/.
>

--=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: David Krauss <potswa@gmail.com>
Date: Wed, 18 Mar 2015 10:53:28 +0800
Raw View
> On 2015=E2=80=9303=E2=80=9318, at 10:52 AM, Douglas Boffey <douglas.boffe=
y@gmail.com> wrote:
>=20
> Excuse my ignorance, but what is EBCO?

Empty Base Class Optimization.

--=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: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Tue, 17 Mar 2015 20:48:20 -0700 (PDT)
Raw View
------=_Part_92_1582984131.1426650500319
Content-Type: multipart/alternative;
 boundary="----=_Part_93_39387034.1426650500319"

------=_Part_93_39387034.1426650500319
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Sunday, March 15, 2015 at 2:38:52 AM UTC-7, andrew....@gmail.com wrote:
>
> Right now there is no good way to conditionally include member variable=
=20
> into a structure definition. This ability is important, for example, to=
=20
> avoid allocating space for empty members and thus bloating structure size=
=20
> (example: generic container with user-defined allocator; allocator is oft=
en=20
> an empty structure).
>
....

> The proposal is to add a construct (member variable with type "void") tha=
t=20
> would essentially be skipped by the compiler without affecting structure=
=20
> layout. Accessing such member variable (value or address) would be a=20
> compile-time error. Then code pieces above could be rewritten like this:
> template<typename T> using nonempty_only =3D=20
> std::conditional_t<std::is_empty<T>::value, void, T>;
> template<typename T, typename Al> struct my_container {
>   T *data;
>   nonempty_only<Al> alloc; // won't affect layout if Al is empty
> };
> template<message_type Type> struct message {
>   message_header header;
>   nonempty_only<message_payload<Type>> payload;
> };
>

I'm starting a new branch of the thread because it just occurred to me this=
=20
afternoon that Andrew's original post mentioned implications for SFINAE=20
that every response so far (especially my own) has ignored.  What he was=20
initially proposing was not merely a way to make a member take zero space,=
=20
or remove special-casing for members of type void, but to actually=20
conditionally compile the member itself! I.e., a sort of static_if=20
<http://citeseerx.ist.psu.edu/viewdoc/download?doi=3D10.1.1.386.5008&rep=3D=
rep1&type=3Dpdf>=20
for member declarations.

struct S {
    std::conditional_t<true, int, void> i;
    std::conditional_t<false, int, void> j;  // member j "does not exist"=
=20
anymore
};

auto foo(auto s) -> decltype(s.i) { return s.i; }  // FOO 1, participates=
=20
only if s.i exists
auto foo(auto t) -> decltype(t.j) { return t.j; }  // FOO 2, participates=
=20
only if t.j exists

int main() { S s; foo(s); }

SFINAE ensures that foo(s) is unambiguously a call to FOO 1 in this case.
If this is really an integral part of Andrew's proposal =E2=80=94 or if it =
isn't *but=20
should be* =E2=80=94 then we have to go back to the drawing board. Having a=
 member=20
variable that "takes no space" is quite a different thing from not having=
=20
that member at all!

(I'm certainly of the strong opinion that std::empty_t is the wrong name=20
for a "non-existent-making" type. Maybe in that case void *would* be=20
appropriate... but I'm unconvinced, as my earlier comments about assigning=
=20
weird ad-hoc behaviors to built-in types are still applicable.)

=E2=80=93Arthur

--=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_93_39387034.1426650500319
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Sunday, March 15, 2015 at 2:38:52 AM UTC-7, andrew....@=
gmail.com 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"lt=
r">Right now there is no good way to conditionally include member variable =
into a structure definition. This ability is important, for example, to avo=
id allocating space for empty members and thus bloating structure size (exa=
mple: generic container with user-defined allocator; allocator is often an =
empty structure).<br></div></blockquote><div>...</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr">The proposal is to add a construct=
 (member variable with type "void") that would essentially be skipped by th=
e compiler without affecting structure layout. Accessing such member variab=
le (value or address) would be a compile-time error. Then code pieces above=
 could be rewritten like this:<br>template&lt;typename T&gt; using nonempty=
_only =3D std::conditional_t&lt;std::is_<wbr>empty&lt;T&gt;::value, void, T=
&gt;;<br>template&lt;typename T, typename Al&gt; struct my_container {<br>&=
nbsp; T *data;<br>&nbsp; nonempty_only&lt;Al&gt; alloc; // won't affect lay=
out if Al is empty<br>};<br>template&lt;message_type Type&gt; struct messag=
e {<br>&nbsp; message_header header;<br>&nbsp; nonempty_only&lt;message_pay=
load&lt;<wbr>Type&gt;&gt; payload;<br>};<br></div></blockquote><div><br></d=
iv><div>I'm starting a new branch of the thread because it just occurred to=
 me this afternoon that Andrew's original post mentioned implications for S=
FINAE that every response so far (especially my own) has ignored. &nbsp;Wha=
t he was initially proposing was not merely a way to make a member take zer=
o space, or remove special-casing for members of type <font face=3D"courier=
 new, monospace">void</font>, but to actually conditionally compile the mem=
ber itself! I.e., a sort of <font face=3D"courier new, monospace"><a href=
=3D"http://citeseerx.ist.psu.edu/viewdoc/download?doi=3D10.1.1.386.5008&amp=
;rep=3Drep1&amp;type=3Dpdf">static_if</a></font> for member declarations.</=
div><div><br></div><div class=3D"prettyprint" style=3D"background-color: rg=
b(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span 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"color: #000;" cl=
ass=3D"styled-by-prettify"><br>&nbsp; &nbsp; std</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify">conditional_t</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">true</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">int</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</s=
pan><span 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"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>&nbsp; &nbsp; std</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">conditional_t</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">false</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"=
>int</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> j</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> &nbsp;</span><span style=3D"color: #800;" class=3D=
"styled-by-prettify">// member j "does not exist" anymore</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></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">auto</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> s</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">decltype</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">s</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">i</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"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> s</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">i</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"> &nbsp;</span><sp=
an style=3D"color: #800;" class=3D"styled-by-prettify">// FOO 1, participat=
es only if s.i exists</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> t</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">-&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">decltype</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">j</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"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> t</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">j</sp=
an><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: #0=
00;" class=3D"styled-by-prettify"> &nbsp;</span><span style=3D"color: #800;=
" class=3D"styled-by-prettify">// FOO 2, participates only if t.j exists</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></spa=
n><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 styl=
e=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: #660;=
" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> S s</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">s</spa=
n><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></div></code></div><div>=
<br></div><div>SFINAE ensures that foo(s) is unambiguously a call to <font =
face=3D"courier new, monospace">FOO 1</font>&nbsp;in this case.</div><div>I=
f this is really an integral part of Andrew's proposal =E2=80=94 or if it i=
sn't <b>but should be</b> =E2=80=94 then we have to go back to the drawing =
board. Having a member variable that "takes no space" is quite a different =
thing from not having that member at all!</div><div><br></div><div>(I'm cer=
tainly of the strong opinion that <font face=3D"courier new, monospace">std=
::empty_t</font> is the wrong name for a "non-existent-making" type. Maybe =
in that case <font face=3D"courier new, monospace">void</font> <i>would</i>=
 be appropriate... but I'm unconvinced, as my earlier comments about assign=
ing weird ad-hoc behaviors to built-in types are still applicable.)</div><d=
iv><br></div><div>=E2=80=93Arthur</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_93_39387034.1426650500319--
------=_Part_92_1582984131.1426650500319--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 17 Mar 2015 22:27:30 -0700 (PDT)
Raw View
------=_Part_5599_452873465.1426656450954
Content-Type: multipart/alternative;
 boundary="----=_Part_5600_762281287.1426656450954"

------=_Part_5600_762281287.1426656450954
Content-Type: text/plain; charset=UTF-8

Then it would seem that the OP is asking for two features, because these
are conceptually different things. On the one hand, you have a member that
certainly exists and can be used, but takes up no actual space in the
object. And on the other, you have a member which does not exist at all;
you can't use it in any way.

I don't think these should be tied together, as they seem to solve two
completely different sets of problems. The "member takes no space" feature
solves the problem of stateless objects that take up needless storage. The
"optional member" solves a completely different problem, where a member
exists or doesn't exist based on compile-time information.

Object storage and object *existence* aren't the same thing. The EBCO
already allows empty objects to have no storage in certain cases, yet those
objects still exist.

--

---
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_5600_762281287.1426656450954
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Then it would seem that the OP is asking for two features,=
 because these are conceptually different things. On the one hand, you have=
 a member that certainly exists and can be used, but takes up no actual spa=
ce in the object. And on the other, you have a member which does not exist =
at all; you can't use it in any way.<br><br>I don't think these should be t=
ied together, as they seem to solve two completely different sets of proble=
ms. The "member takes no space" feature solves the problem of stateless obj=
ects that take up needless storage. The "optional member" solves a complete=
ly different problem, where a member exists or doesn't exist based on compi=
le-time information.<br><br>Object storage and object <i>existence</i> aren=
't the same thing. The EBCO already allows empty objects to have no storage=
 in certain cases, yet those objects still exist.<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&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_5600_762281287.1426656450954--
------=_Part_5599_452873465.1426656450954--

.


Author: andrew.gilewsky@gmail.com
Date: Wed, 18 Mar 2015 11:23:24 -0700 (PDT)
Raw View
------=_Part_628_558167444.1426703004808
Content-Type: multipart/alternative;
 boundary="----=_Part_629_911661212.1426703004809"

------=_Part_629_911661212.1426703004809
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable


On Wednesday, March 18, 2015 at 4:21:22 AM UTC+3, David Krauss wrote:
>
> What=E2=80=99s the use case? A void member cannot be accessed at all, at =
least=20
> without significant further extensions to the language. You only avoid th=
e=20
> need for further specialization when the implicit instantiations won=E2=
=80=99t ever=20
> use that member.
>
> Perhaps it=E2=80=99s useful for dumb container templates, but that sugges=
ts the=20
> template is either poorly designed or so generic (e.g. std::tuple) that=
=20
> the EBCO is applicable.
>
Example that immediately comes to mind:
template<typename T> struct safe_call_result { bool success; T result; };
template<typename Func, typename... Args> auto safe_call(Func f, Args &&...=
=20
args) -> safe_call_result<std::result_of_t<Func(Args...)>> { ... }

void f(int a) { ... }
auto res =3D safe_call(f, x);
if (res.success) ...

Other examples would be std::future and similar structures. Of course,=20
functions should have special code that would avoid attempting to=20
read/write 'void member' (that can be wrapped in some helper function or=20
macro), but structure *itself* won't need to special-case 'void' template=
=20
argument (that would involve duplicating other member definitions).

--=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_629_911661212.1426703004809
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br>On Wednesday, March 18, 2015 at 4:21:22 AM UTC+3, Davi=
d Krauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"w=
ord-wrap:break-word"><div>What=E2=80=99s the use case? A void member cannot=
 be accessed at all, at least without significant further extensions to the=
 language. You only avoid the need for further specialization when the impl=
icit instantiations won=E2=80=99t ever use that member.</div><div><br></div=
><div>Perhaps it=E2=80=99s useful for dumb container templates, but that su=
ggests the template is either poorly designed or so generic (e.g. <font fac=
e=3D"Courier">std::tuple</font>) that the EBCO is applicable.</div></div></=
blockquote><div>Example that immediately comes to mind:<br>template&lt;type=
name T&gt; struct safe_call_result { bool success; T result; };<br>template=
&lt;typename Func, typename... Args&gt; auto safe_call(Func f, Args &amp;&a=
mp;... args) -&gt; safe_call_result&lt;std::result_of_t&lt;Func(Args...)&gt=
;&gt; { ... }<br><br>void f(int a) { ... }<br>auto res =3D safe_call(f, x);=
<br>if (res.success) ...<br><br>Other examples would be std::future and sim=
ilar structures. Of course, functions should have special code that would a=
void attempting to read/write 'void member' (that can be wrapped in some he=
lper function or macro), but structure <i>itself</i> won't need to special-=
case 'void' template argument (that would involve duplicating other member =
definitions).<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_629_911661212.1426703004809--
------=_Part_628_558167444.1426703004808--

.


Author: andrew.gilewsky@gmail.com
Date: Wed, 18 Mar 2015 11:31:48 -0700 (PDT)
Raw View
------=_Part_836_985923942.1426703508628
Content-Type: multipart/alternative;
 boundary="----=_Part_837_439872942.1426703508628"

------=_Part_837_439872942.1426703508628
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Wednesday, March 18, 2015 at 6:48:20 AM UTC+3, Arthur O'Dwyer wrote:
>
> I'm starting a new branch of the thread because it just occurred to me=20
> this afternoon that Andrew's original post mentioned implications for=20
> SFINAE that every response so far (especially my own) has ignored.  What =
he=20
> was initially proposing was not merely a way to make a member take zero=
=20
> space, or remove special-casing for members of type void, but to actually=
=20
> conditionally compile the member itself! I.e., a sort of static_if=20
> <http://citeseerx.ist.psu.edu/viewdoc/download?doi=3D10.1.1.386.5008&rep=
=3Drep1&type=3Dpdf>=20
> for member declarations.
>
=20

> If this is really an integral part of Andrew's proposal =E2=80=94 or if i=
t isn't *but=20
> should be* =E2=80=94 then we have to go back to the drawing board. Having=
 a=20
> member variable that "takes no space" is quite a different thing from not=
=20
> having that member at all!
>
> (I'm certainly of the strong opinion that std::empty_t is the wrong name=
=20
> for a "non-existent-making" type. Maybe in that case void *would* be=20
> appropriate... but I'm unconvinced, as my earlier comments about assignin=
g=20
> weird ad-hoc behaviors to built-in types are still applicable.)
>
> =E2=80=93Arthur
>
Indeed, I originally thought about 'void' member as essentially 'missing'.=
=20
Not sure whether the described interaction with SFINAE is a *good* thing,=
=20
need to think more about it.

For problems described in original proposal, *practically* there is not a=
=20
big difference between 'missing member' and 'member taking zero space' -=20
both are workable solutions. The difference is essentially whether=20
decltype(S::m) is 'void' or error. In both cases appropriate dispatch code=
=20
could be written.

--=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_837_439872942.1426703508628
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, March 18, 2015 at 6:48:20 AM UTC+3, Arthur O=
'Dwyer wrote:<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">=
I'm starting a new branch of the thread because it just occurred to me this=
 afternoon that Andrew's original post mentioned implications for SFINAE th=
at every response so far (especially my own) has ignored. &nbsp;What he was=
 initially proposing was not merely a way to make a member take zero space,=
 or remove special-casing for members of type <font face=3D"courier new, mo=
nospace">void</font>, but to actually conditionally compile the member itse=
lf! I.e., a sort of <font face=3D"courier new, monospace"><a href=3D"http:/=
/citeseerx.ist.psu.edu/viewdoc/download?doi=3D10.1.1.386.5008&amp;rep=3Drep=
1&amp;type=3Dpdf" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'http://www.google.com/url?q\75http%3A%2F%2Fciteseerx.ist.psu.edu%2Fvi=
ewdoc%2Fdownload%3Fdoi%3D10.1.1.386.5008%26rep%3Drep1%26type%3Dpdf\46sa\75D=
\46sntz\0751\46usg\75AFQjCNEuVSj0ajgC9MF0MfE6JhQGcTnEJg';return true;" oncl=
ick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fciteseerx.is=
t.psu.edu%2Fviewdoc%2Fdownload%3Fdoi%3D10.1.1.386.5008%26rep%3Drep1%26type%=
3Dpdf\46sa\75D\46sntz\0751\46usg\75AFQjCNEuVSj0ajgC9MF0MfE6JhQGcTnEJg';retu=
rn true;">static_if</a></font> for member declarations.</div></blockquote><=
div>&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"lt=
r">If this is really an integral part of Andrew's proposal =E2=80=94 or if =
it isn't <b>but should be</b> =E2=80=94 then we have to go back to the draw=
ing board. Having a member variable that "takes no space" is quite a differ=
ent thing from not having that member at all!<div><br></div><div>(I'm certa=
inly of the strong opinion that <font face=3D"courier new, monospace">std::=
empty_t</font> is the wrong name for a "non-existent-making" type. Maybe in=
 that case <font face=3D"courier new, monospace">void</font> <i>would</i> b=
e appropriate... but I'm unconvinced, as my earlier comments about assignin=
g weird ad-hoc behaviors to built-in types are still applicable.)</div><div=
><br></div><div>=E2=80=93Arthur</div></div></blockquote><div>Indeed, I orig=
inally thought about 'void' member as essentially 'missing'. Not sure wheth=
er the described interaction with SFINAE is a <i>good</i> thing, need to th=
ink more about it.<br><br>For problems described in original proposal, <i>p=
ractically</i> there is not a big difference between 'missing member' and '=
member taking zero space' - both are workable solutions. The difference is =
essentially whether decltype(S::m) is 'void' or error. In both cases approp=
riate dispatch code could be written.<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_837_439872942.1426703508628--
------=_Part_836_985923942.1426703508628--

.