Topic: Another alternative to EBO: Unused member
Author: =?UTF-8?Q?Jonathan_M=c3=bcller?= <jonathanmueller.dev@gmail.com>
Date: Thu, 7 Jul 2016 11:03:48 +0200
Raw View
This is a multi-part message in MIME format.
--------------961A388CBE097D81C5D52FE8
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
This is a suggestion for a different approach to "solve" EBO.
Responses to Allow zero size arrays and let them occupy zero bytes=20
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/51e6aec9-a745=
-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter=
>=20
mentioned that the C++ object model cannot have anything that has size 0.
So I got a completely different idea based on the fact that empty types=20
are only needed for their member functions.
1. (optional, required for current empty types to work) Make member
functions that don't access any non-static member variables or
functions implicitly static.
This shouldn't break any existing code because you can call a static
member function with the same syntax as a non-member function, so
any code calling a member function can also call a static function
without change.
2. "Encourage" - like with the RVO - compilers to remove objects that
are only used to call static member functions. Of course once the
actual object is required (i.e. if you take the address of it), this
optimization cannot happen.
With these changes you can simply write the following generic code:
|
structempty_policy
{
/*static*/voiddo_sth();
};
template<classPolicy>
classgeneric_type
{
public:
voiddo_sth_fancy()
{
++value;
policy.do_sth();
}
private:
intvalue;
Policypolicy;
};
|
Becausepolicy is only used to call a (implictly) static member
function, it will be optimized out
andsizeof(generic_type<empty_policy>) will be sizeof(int).
If you instantiate it with a non-empty type, however, this is not
the case.
This approach is cumbersome, however: It is very easy to write code
that depends on the address of policy,
I thus also suggest:
3. A new attribute: maybe_empty(or a completely different name). It
informs the compiler that a member could be empty for some type and
warns if you write code that requires its existence.
With this attribute, writing generic code is much easier.
There is still a problem though: Often you provide an accessor
function to the policy, the usual signature is:
|
constPolicy&get_policy()const;
|
But this would break the optimization because you form a reference
to the empty object and thus require its existence in memory.
You need to resolve to a std::conditionalor a similar solution to
return it by-value. To ease that I also suggest:
4. A standard library addition: std::empty_reference<T>(or a completely
different name).
It could be a simple alias for
std::conditional_t<std::is_empty_v<T>, std::remove_cv_t<T>, T&>or a
fully fledged class if need be.
With all those changes usage would look like so:
|
Entercode here...
|
structempty_policy
{
/*static*/voiddo_sth();
};
template<classPolicy>
classgeneric_type
{
public:
voiddo_sth_fancy()
{
++value;
policy.do_sth();
}
std::empty_reference<const Policy> get_policy() const
{
return policy;
}
private:
intvalue;
[[maybe_empty]] Policypolicy;
};
|
|
This is just a rough sketch, there might be issues (like the copy/move=20
ctors/assignment operators for empty types and their ability to affect=20
the optimization),
but what do you think?
Jonathan M=C3=BCller
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/f1db85ca-d868-8fad-0a80-5f47350fb448%40gmail.com=
..
--------------961A388CBE097D81C5D52FE8
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"content-type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
This is a suggestion for a different approach to "solve" EBO.<br>
Responses to <a
href=3D"https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/51e6ae=
c9-a745-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=3Demail&utm_sour=
ce=3Dfooter">Allow
zero size arrays and let them occupy zero bytes</a> mentioned that
the C++ object model cannot have anything that has size 0.<br>
So I got a completely different idea based on the fact that empty
types are only needed for their member functions.<br>
<ol>
<li>(optional, required for current empty types to work) Make
member functions that don't access any non-static member
variables or functions implicitly static.<br>
This shouldn't break any existing code because you can call a
static member function with the same syntax as a non-member
function, so any code calling a member function can also call a
static function without change.<br>
</li>
<li>"Encourage" - like with the RVO - compilers to remove objects
that are only used to call static member functions. Of course
once the actual object is required (i.e. if you take the address
of it), this optimization cannot happen.<br>
<br>
With these changes you can simply write the following generic
code:<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
250); border-color: rgb(187, 187, 187); border-style: solid;
border-width: 1px; word-wrap: break-word;"><code
class=3D"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">
empty_policy<br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">{</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #800;"
class=3D"styled-by-prettify">/*static*/</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
style=3D"color: #008;" class=3D"styled-by-prettify">void</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> do_sth=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">};</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"><br>
<br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">template</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span
style=3D"color: #008;" class=3D"styled-by-prettify">class</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
style=3D"color: #606;" class=3D"styled-by-prettify">Policy<=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">></s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">class</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
generic_type<br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">{</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">public</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">:</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">void</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
do_sth_fancy</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">()</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">{</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">++</span><span style=3D"color:
#000;" class=3D"styled-by-prettify">value</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 policy</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">.</span><span style=3D"color:
#000;" class=3D"styled-by-prettify">do_sth</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"><br>
<br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">private</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">:</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">int</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"> value</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #606;"
class=3D"styled-by-prettify">Policy</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> policy=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">};</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"><br>
</span></div>
</code></div>
<br>
Because<span style=3D"font-family: courier new,monospace;"> policy<=
/span>
is only used to call a (implictly) static member function, it
will be optimized out and<span style=3D"font-family: courier
new,monospace;"> sizeof(generic_type<empty_policy>)</span>
will be <span style=3D"font-family: courier new,monospace;">sizeof(=
int)</span>.<br>
If you instantiate it with a non-empty type, however, this is
not the case.<br>
<br>
This approach is cumbersome, however: It is very easy to write
code that depends on the address of <font face=3D"courier
new,monospace">policy<font face=3D"arial,sans-serif">,</font></fo=
nt><br>
<font face=3D"courier new,monospace"><font face=3D"arial,sans-serif=
">I
thus also suggest:<br>
</font></font><br>
</li>
<li>A new attribute: <font face=3D"courier new,monospace">maybe_empty=
<font
face=3D"arial,sans-serif"> (or a completely different name).
It informs the compiler that a member could be empty for
some type and warns if you write code that requires its
existence.<br>
With this attribute, writing generic code is much easier.<br>
<br>
There is still a problem though: Often you provide an
accessor function to the policy, the usual signature is:<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250,
250, 250); border-color: rgb(187, 187, 187); border-style:
solid; border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><font
face=3D"arial,sans-serif"><span style=3D"color: #008;"
class=3D"styled-by-prettify">const</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span
style=3D"color: #606;" class=3D"styled-by-prettify">P=
olicy</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">&=
amp;</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
get_policy</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">()</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span
style=3D"color: #008;" class=3D"styled-by-prettify">c=
onst</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;=
</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>
</span></font></div>
</code></div>
But this would break the optimization because you form a
reference to the empty object and thus require its existence
in memory.<br>
You need to resolve to a <font face=3D"courier new,monospace">s=
td::conditional<font
face=3D"arial,sans-serif"> or a similar solution to return
it by-value. To ease that I also suggest:<br>
<br>
</font></font></font></font></li>
<li><font face=3D"courier new,monospace"><font
face=3D"arial,sans-serif"><font face=3D"courier new,monospace">=
<font
face=3D"arial,sans-serif">A standard library addition: <fon=
t
face=3D"courier new,monospace">std::empty_reference<T&=
gt;<font
face=3D"arial,sans-serif"> (or a completely different
name).<br>
I</font></font>t could be a simple alias for <font
face=3D"courier new,monospace">std::conditional_t<std:=
:is_empty_v<T>,
std::remove_cv_t<T>, T&><font
face=3D"arial,sans-serif"> or a fully fledged class if
need be.</font><br>
</font></font></font></font></font></li>
</ol>
<p><font face=3D"arial,sans-serif">With all those changes usage would
look like so:</font></p>
<div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
250); border-color: rgb(187, 187, 187); border-style: solid;
border-width: 1px; word-wrap: break-word;"><font
face=3D"arial,sans-serif"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #606;"
class=3D"styled-by-prettify">Enter</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"> code here</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">...</span=
>
<div class=3D"prettyprint" style=3D"background-color: rgb(250,
250, 250); border-color: rgb(187, 187, 187); border-style:
solid; border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">struct</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
empty_policy<br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">{</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 </span><span style=3D"color: #800;"
class=3D"styled-by-prettify">/*static*/</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span
style=3D"color: #008;" class=3D"styled-by-prettify">voi=
d</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
do_sth</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">();</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">};</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
<br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">template</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: #008;" class=3D"styled-by-prettify">cla=
ss</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span
style=3D"color: #606;" class=3D"styled-by-prettify">Pol=
icy</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">>=
;</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">class</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
generic_type<br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">{</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">public</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">:</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">void</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
do_sth_fancy</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">()</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">{</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 =C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">++</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">val=
ue</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 =C2=A0 policy</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">.</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">do_=
sth</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();=
</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
<br>
=C2=A0 std::empty_reference<co<font
face=3D"arial,sans-serif">nst </font>Policy>
get_<font face=3D"arial,sans-serif">policy() const</fon=
t><br>
=C2=A0<font face=3D"arial,sans-serif">=C2=A0 {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return policy;<b=
r>
=C2=A0 =C2=A0 }</font>=C2=A0 <br>
<br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">private</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">:</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">int</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
value</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
=C2=A0 [[maybe_empty]] </span><span style=3D"color: #60=
6;"
class=3D"styled-by-prettify">Policy</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
policy</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">};</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>
</span></div>
</code></div>
</div>
</code></font></div>
<p><br>
</p>
<p>This is just a rough sketch, there might be issues (like the
copy/move ctors/assignment operators for empty types and their
ability to affect the optimization),</p>
<p>but what do you think?</p>
Jonathan M=C3=BCller
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/f1db85ca-d868-8fad-0a80-5f47350fb448%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/f1db85ca-d868-8fad-0a80-5f47350fb448%=
40gmail.com</a>.<br />
--------------961A388CBE097D81C5D52FE8--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 7 Jul 2016 07:22:46 -0700 (PDT)
Raw View
------=_Part_102_742524247.1467901366163
Content-Type: multipart/alternative;
boundary="----=_Part_103_469048454.1467901366164"
------=_Part_103_469048454.1467901366164
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, July 7, 2016 at 5:03:52 AM UTC-4, Jonathan M=C3=BCller wrote:
>
> This is a suggestion for a different approach to "solve" EBO.
>
Why do people keep talking about this in terms of EBO, like that's the only=
=20
reason why you would ever want a member to take up no space?
Responses to Allow zero size arrays and let them occupy zero bytes=20
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/51e6aec9-a7=
45-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>=20
> mentioned that the C++ object model cannot have anything that has size 0.
> So I got a completely different idea based on the fact that empty types=
=20
> are only needed for their member functions.
>
> 1. (optional, required for current empty types to work) Make member=20
> functions that don't access any non-static member variables or functio=
ns=20
> implicitly static.
> =20
> So, a member function which calls a sibling member function that doesn't=
=20
access NSDMs wouldn't be allowed? That's a pretty harsh requirement. And a=
=20
very unnecessary one.
And what if the type has its own member which is empty by this definition?=
=20
Are you saying that nested empty members don't work:
struct Empty1 { void DoSomething() {}};
struct Empty2 {Empty 1 e; void DoSomething() {e.DoSomething();}};
Why should `Empty2` not be just as empty as `Empty1`?
Also, you are now doing something never before seen in C++: you are=20
changing the definition of a class based on the definition of one of its=20
member functions. Naturally that requires those member functions to be=20
inline. Consider this:
struct Empty
{
void DoSomething();
};
struct Full
{
int foo;
Empty bar;
};
You are saying that `sizeof(Full)` depends on the eventual definition of=20
`DoSomething`. This means that compilers have to do one of the following:
1. In the absence of the definition of any member function, assume that the=
=20
class is not stateless until all member function definitions are found.
Which means that `sizeof(Full)` will be 8 bytes or so. And yet, if you do=
=20
this afterwards:
inline void Empty::DoSomething() {}
struct Full2
{
int foo;
Empty bar;
};
`sizeof(Full2)` will be 4. That's rather surprising, yes?
2. In the absence of the definition of any members, wait until the entire=
=20
translation unit is fully explorered before determining the sizes of=20
classes.
3. Unless all members are defined within the class itself, the class can=20
never be stateless.
>
> 1. This shouldn't break any existing code because you can call a=20
> static member function with the same syntax as a non-member function, =
so=20
> any code calling a member function can also call a static function wit=
hout=20
> change.
> 2. "Encourage" - like with the RVO - compilers to remove objects that=
=20
> are only used to call static member functions. Of course once the actu=
al=20
> object is required (i.e. if you take the address of it), this optimiza=
tion=20
> cannot happen.
> =20
> You're effectively saying that I can declare a class that includes an=20
empty class as a public member. And that public member will suddenly take=
=20
up space if *any code anywhere* takes the address of that member? There is=
=20
no way that would work. You're saying that the compiler would have to=20
compile the *entire source code*, fully linked and everything, before it=20
could know if it could optimize a variable away.
Unless you're saying that taking the address of a member can provoke an ODR=
=20
violation. Which is much worse.
No, this is just not workable. However it is you want to make a subobject=
=20
stateless, this *cannot* be implicit. You need some syntax to explicitly=20
declare that you are invoking this power, either at the site of a member's=
=20
declaration or at the site of a type's definition (or both).
>
> 1.=20
> With these changes you can simply write the following generic code:
> struct empty_policy
> {
> /*static*/ void do_sth();
> };
> =20
> template <class Policy>
> class generic_type
> {
> public:
> void do_sth_fancy()
> {
> ++value;
> policy.do_sth();
> }
> =20
> private:
> int value;
> Policy policy;
> };
> =20
> Because policy is only used to call a (implictly) static member=20
> function, it will be optimized out and=20
> sizeof(generic_type<empty_policy>) will be sizeof(int).
> If you instantiate it with a non-empty type, however, this is not the=
=20
> case.
> =20
> You said "will be". If that's the case, then this is not like RBO, since=
=20
that's not required. So is this required or is it not?
>
> 1.=20
> This approach is cumbersome, however: It is very easy to write code=20
> that depends on the address of policy,
> I thus also suggest:
> =20
> 2. A new attribute
>
> No. Stop using attributes to solve problems. *Especially* this one.
This is just a rough sketch, there might be issues (like the copy/move=20
> ctors/assignment operators for empty types and their ability to affect th=
e=20
> optimization),
but what do you think?
>
You're essentially trying to define away the problem by making the object=
=20
not actually be a member. It's an interesting solution to the problem, but=
=20
I don't think it's the best way to handle it.
The basic problem with stateless members is that they violate one of two=20
C++ rules: 1) Objects must occupy a region of storage, 2) different=20
instances of objects must occupy different regions of storage. In order to=
=20
have stateless objects, one of these rules must be changed.
I think changing rule #1 is folly, because that rule is a very fundamental=
=20
foundation of the entire C++ object model. The fallout of making such a=20
change is not well understood. Rule #2 is not quite so inviolate, because=
=20
we allow base classes to get away with it.
I think the most effective way to move forward is to make changes to rule=
=20
#2 which allows member subobjects (properly designated via some syntax) to=
=20
not occupy a unique region of storage. It would allow us to make such=20
stateless subobjects to be as regular as possible; they work like regular=
=20
objects except where necessary in order for them to take up no space in=20
their containing object's layout.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/46d11db4-a77b-4cdb-a9ee-97ffea9e23d0%40isocpp.or=
g.
------=_Part_103_469048454.1467901366164
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, July 7, 2016 at 5:03:52 AM UTC-4, Jonathan M=
=C3=BCller wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
This is a suggestion for a different approach to "solve" EBO.=
<br></div></blockquote><div><br>Why do people keep talking about this in te=
rms of EBO, like that's the only reason why you would ever want a membe=
r to take up no space?<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
Responses to <a href=3D"https://groups.google.com/a/isocpp.org/d/msgid/=
std-proposals/51e6aec9-a745-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=
=3Demail&utm_source=3Dfooter" target=3D"_blank" rel=3D"nofollow" onmous=
edown=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/51e6aec9-a745-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter';return true;" onclick=3D"this.href=3D&#=
39;https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/51e6aec9-a7=
45-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium\x3demail\x26utm_source\x3=
dfooter';return true;">Allow
zero size arrays and let them occupy zero bytes</a> mentioned that
the C++ object model cannot have anything that has size 0.<br>
So I got a completely different idea based on the fact that empty
types are only needed for their member functions.<br>
<ol>
<li>(optional, required for current empty types to work) Make
member functions that don't access any non-static member
variables or functions implicitly static.<br></li></ol></div></bloc=
kquote><div>So, a member function which calls a sibling member function tha=
t doesn't access NSDMs wouldn't be allowed? That's a pretty har=
sh requirement. And a very unnecessary one.<br><br>And what if the type has=
its own member which is empty by this definition? Are you saying that nest=
ed empty members don't work:<br><br><div class=3D"prettyprint" style=3D=
"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bo=
rder-style: solid; border-width: 1px; word-wrap: break-word;"><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;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"sty=
led-by-prettify">Empty1</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">DoSomething</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;" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">struct</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">Empty2</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: #606;" class=3D"styled-by-prettify">Empty</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> e</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">DoS=
omething</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">e</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #606;" =
class=3D"styled-by-prettify">DoSomething</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">();}};</span></div></code></div><br>Why shoul=
d `Empty2` not be just as empty as `Empty1`?<br><br>Also, you are now doing=
something never before seen in C++: you are changing the definition of a c=
lass based on the definition of one of its member functions. Naturally that=
requires those member functions to be inline. Consider this:<br><br><div c=
lass=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-=
color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wra=
p: break-word;"><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"> </span><span style=3D=
"color: #606;" class=3D"styled-by-prettify">Empty</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">DoSomething</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Full</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Empty</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span></div><=
/code></div><br>You are saying that `sizeof(Full)` depends on the eventual =
definition of `DoSomething`. This means that compilers have to do one of th=
e following:<br><br>1. In the absence of the definition of any member funct=
ion, assume that the class is not stateless until all member function defin=
itions are found.<br><br>Which means that `sizeof(Full)` will be 8 bytes or=
so. And yet, if you do this afterwards:<br><br><div class=3D"prettyprint" =
style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, =
187); border-style: solid; border-width: 1px; word-wrap: break-word;"><code=
class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: =
#008;" class=3D"styled-by-prettify">inline</span><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: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Empty</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #606;" class=3D"styled-by-prettify">DoSo=
mething</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
06;" class=3D"styled-by-prettify">Full2</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">int</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"><br>=
=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Emp=
ty</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> bar</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br>`s=
izeof(Full2)` will be 4. That's rather surprising, yes?<br><br>2. In th=
e absence of the definition of any members, wait until the entire translati=
on unit is fully explorered before determining the sizes of classes.<br><br=
>3. Unless all members are defined within the class itself, the class can n=
ever be stateless.<br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv bgcolor=3D"#FFFFFF" text=3D"#000000"><ol><li>
This shouldn't break any existing code because you can call a
static member function with the same syntax as a non-member
function, so any code calling a member function can also call a
static function without change.<br>
</li>
<li>"Encourage" - like with the RVO - compilers to remove o=
bjects
that are only used to call static member functions. Of course
once the actual object is required (i.e. if you take the address
of it), this optimization cannot happen.<br></li></ol></div></block=
quote><div>You're effectively saying that I can declare a class that in=
cludes an empty class as a public member. And that public member will sudde=
nly take up space if <i>any code anywhere</i> takes the address of that mem=
ber? There is no way that would work. You're saying that the compiler w=
ould have to compile the <i>entire source code</i>, fully linked and everyt=
hing, before it could know if it could optimize a variable away.<br><br>Unl=
ess you're saying that taking the address of a member can provoke an OD=
R violation. Which is much worse.<br><br>No, this is just not workable. How=
ever it is you want to make a subobject stateless, this <i>cannot</i> be im=
plicit. You need some syntax to explicitly declare that you are invoking th=
is power, either at the site of a member's declaration or at the site o=
f a type's definition (or both).<br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000"><ol><li>
<br>
With these changes you can simply write the following generic
code:<br>
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(18=
7,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code>
<div><span style=3D"color:#008">struct</span><span style=3D"col=
or:#000">
empty_policy<br>
</span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>
=C2=A0 </span><span style=3D"color:#800">/*static*/</span><=
span style=3D"color:#000"> </span><span style=3D"color:#008">void</span><sp=
an style=3D"color:#000"> do_sth</span><span style=3D"color:#660">();</span>=
<span style=3D"color:#000"><br>
</span><span style=3D"color:#660">};</span><span style=3D"col=
or:#000"><br>
<br>
</span><span style=3D"color:#008">template</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">class</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Policy</span><span style=3D"color:#660">></span><span st=
yle=3D"color:#000"><br>
</span><span style=3D"color:#008">class</span><span style=3D"=
color:#000">
generic_type<br>
</span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>
</span><span style=3D"color:#008">public</span><span style=3D=
"color:#660">:</span><span style=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#008">void</span><span s=
tyle=3D"color:#000">
do_sth_fancy</span><span style=3D"color:#660">()</span><spa=
n style=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#660">{</span><span styl=
e=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">++</span><s=
pan style=3D"color:#000">value</span><span style=3D"color:#660">;</span><sp=
an style=3D"color:#000"><br>
=C2=A0 =C2=A0 policy</span><span style=3D"color:#660">.</sp=
an><span style=3D"color:#000">do_sth</span><span style=3D"color:#660">();</=
span><span style=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#660">}</span><span styl=
e=3D"color:#000"><br>
<br>
</span><span style=3D"color:#008">private</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#008">int</span><span st=
yle=3D"color:#000"> value</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#606">Policy</span><span=
style=3D"color:#000"> policy</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"><br>
</span><span style=3D"color:#660">};</span><span style=3D"col=
or:#000"><br>
</span></div>
</code></div>
<br>
Because<span style=3D"font-family:courier new,monospace"> policy</s=
pan>
is only used to call a (implictly) static member function, it
will be optimized out and<span style=3D"font-family:courier new,mon=
ospace"> sizeof(generic_type<empty_<wbr>policy>)</span>
will be <span style=3D"font-family:courier new,monospace">sizeof(in=
t)</span>.<br>
If you instantiate it with a non-empty type, however, this is
not the case.<br></li></ol></div></blockquote><div>You said "w=
ill be". If that's the case, then this is not like RBO, since that=
's not required. So is this required or is it not?<br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000"=
><ol><li>
<br>
This approach is cumbersome, however: It is very easy to write
code that depends on the address of <font face=3D"courier
new,monospace">policy<font face=3D"arial,sans-serif">,</font></fo=
nt><br>
<font face=3D"courier new,monospace"><font face=3D"arial,sans-serif=
">I
thus also suggest:<br>
</font></font><br>
</li>
<li>A new attribute</li></ol></div></blockquote><div>No. Stop using a=
ttributes to solve problems. <i>Especially</i> this one.<br><br><blockquote=
style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 2=
04); padding-left: 1ex;" class=3D"gmail_quote">This is just a rough sketch,=
there might be issues (like the
copy/move ctors/assignment operators for empty types and their
ability to affect the optimization),</blockquote></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<p>but what do you think?</p></div></blockquote><div><br>You're ess=
entially trying to define away the problem by making the object not actuall=
y be a member. It's an interesting solution to the problem, but I don&#=
39;t think it's the best way to handle it.<br><br>The basic problem wit=
h stateless members is that they violate one of two C++ rules: 1) Objects m=
ust occupy a region of storage, 2) different instances of objects must occu=
py different regions of storage. In order to have stateless objects, one of=
these rules must be changed.<br><br>I think changing rule #1 is folly, bec=
ause that rule is a very fundamental foundation of the entire C++ object mo=
del. The fallout of making such a change is not well understood. Rule #2 is=
not quite so inviolate, because we allow base classes to get away with it.=
<br><br>I think the most effective way to move forward is to make changes t=
o rule #2 which allows member subobjects (properly designated via some synt=
ax) to not occupy a unique region of storage. It would allow us to make suc=
h stateless subobjects to be as regular as possible; they work like regular=
objects except where necessary in order for them to take up no space in th=
eir containing object's layout.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/46d11db4-a77b-4cdb-a9ee-97ffea9e23d0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/46d11db4-a77b-4cdb-a9ee-97ffea9e23d0=
%40isocpp.org</a>.<br />
------=_Part_103_469048454.1467901366164--
------=_Part_102_742524247.1467901366163--
.
Author: =?UTF-8?Q?Jonathan_M=C3=BCller?= <jonathanmueller.dev@gmail.com>
Date: Thu, 7 Jul 2016 08:37:51 -0700 (PDT)
Raw View
------=_Part_4532_319656666.1467905871590
Content-Type: multipart/alternative;
boundary="----=_Part_4533_1312009939.1467905871591"
------=_Part_4533_1312009939.1467905871591
Content-Type: text/plain; charset=UTF-8
On Thursday, July 7, 2016 at 4:22:46 PM UTC+2, Nicol Bolas wrote:
> Why do people keep talking about this in terms of EBO, like that's the
> only reason why you would ever want a member to take up no space?
>
No, because that's the only way to have empty members.
So every solution would be a replacement for EBO.
So, a member function which calls a sibling member function that doesn't
> access NSDMs wouldn't be allowed? That's a pretty harsh requirement. And a
> very unnecessary one.
>
Many negations, let me grasp this:
A member function that calls a sibling member function.
The sibling member function doesn't access NSDMS, thus it is implictly
static.
And thus the original member function is implictly static.
> And what if the type has its own member which is empty by this definition?
> Are you saying that nested empty members don't work:
>
> struct Empty1 { void DoSomething() {}};
> struct Empty2 {Empty 1 e; void DoSomething() {e.DoSomething();}};
>
> Why should `Empty2` not be just as empty as `Empty1`?
>
`Empty2` should be just as empty as `Empty1`, yes.
> Also, you are now doing something never before seen in C++: you are
> changing the definition of a class based on the definition of one of its
> member functions. Naturally that requires those member functions to be
> inline. Consider this:
>
> struct Empty
> {
> void DoSomething();
> };
>
> struct Full
> {
> int foo;
> Empty bar;
> };
>
> You are saying that `sizeof(Full)` depends on the eventual definition of
> `DoSomething`. This means that compilers have to do one of the following:
>
No, because `Empty` doesn't have any member variables, `DoSomething` cannot
possibly access any member variables and is thus implicitly static.
> You said "will be". If that's the case, then this is not like RBO, since
> that's not required. So is this required or is it not?
>
My mistake, I meant copy elision, not RVO. It is required.
> No. Stop using attributes to solve problems. *Especially* this one.
>
Isn't that exactly why attributes are there?
Note that the attribute has no influence on the optimization or similar, it
will be performed anyway.
The attribute just warns if the optimization cannot be performed.
There are already similar GCC/Clang attributes.
> You're essentially trying to define away the problem by making the object
> not actually be a member. It's an interesting solution to the problem, but
> I don't think it's the best way to handle it.
>
Yes, that's my idea.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/ef370ae4-4e1e-4370-8cd1-1f812c7473b1%40isocpp.org.
------=_Part_4533_1312009939.1467905871591
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>On Thursday, July 7, 2016 at 4:22:46 PM UTC+2, Nicol B=
olas wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><div>Why do people keep talking about this in terms of EBO, like that'=
;s the only reason why you would ever want a member to take up no space?<br=
></div></div></blockquote><div>No, because that's the only way to have =
empty members.<br>So every solution would be a replacement for EBO.<br><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">So, a m=
ember function which calls a sibling member function that doesn't acces=
s NSDMs wouldn't be allowed? That's a pretty harsh requirement. And=
a very unnecessary one.<br></div></blockquote><div>Many negations, let me =
grasp this:<br>A member function that calls a sibling member function.<br>T=
he sibling member function doesn't access NSDMS, thus it is implictly s=
tatic.<br>And thus the original member function is implictly static.<br>=C2=
=A0</div><div></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div>And what if the type has its own member which is empty by thi=
s definition? Are you saying that nested empty members don't work:<br><=
br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187=
,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div>=
<span style=3D"color:#008">struct</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Empty1</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span=
style=3D"color:#008">void</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#606">DoSomething</span><span style=3D"color:#660">()</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">{}};</span><sp=
an style=3D"color:#000"><br></span><span style=3D"color:#008">struct</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">Empty2</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span=
style=3D"color:#606">Empty</span><span style=3D"color:#000"> </span><span =
style=3D"color:#066">1</span><span style=3D"color:#000"> e</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"=
color:#008">void</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#606">DoSomething</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000">e</span><span style=3D"color:#660">.</span><span style=3D"color:=
#606">DoSomething</span><span style=3D"color:#660">();}};</span></div></cod=
e></div><br>Why should `Empty2` not be just as empty as `Empty1`?<br></div>=
</div></blockquote><div>`Empty2` should be just as empty as `Empty1`, yes.<=
br><br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><div>Also, you are now doing something never before seen in C++: you =
are changing the definition of a class based on the definition of one of it=
s member functions. Naturally that requires those member functions to be in=
line. Consider this:<br><br><div style=3D"background-color:rgb(250,250,250)=
;border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wra=
p:break-word"><code><div><span style=3D"color:#008">struct</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#606">Empty</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">void</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">DoSomething</spa=
n><span style=3D"color:#660">();</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">};</span><span style=3D"color:#000"><br><br></=
span><span style=3D"color:#008">struct</span><span style=3D"color:#000"> </=
span><span style=3D"color:#606">Full</span><span style=3D"color:#000"><br><=
/span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 </span><span style=3D"color:#008">int</span><span style=3D"color:#000">=
foo</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><b=
r>=C2=A0 </span><span style=3D"color:#606">Empty</span><span style=3D"color=
:#000"> bar</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br></span><span style=3D"color:#660">};</span></div></code></div><br>=
You are saying that `sizeof(Full)` depends on the eventual definition of `D=
oSomething`. This means that compilers have to do one of the following:<br>=
</div></div></blockquote><div>No, because `Empty` doesn't have any memb=
er variables, `DoSomething` cannot possibly access any member variables and=
is thus implicitly static.<br>=C2=A0</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">You said "will be". If that's t=
he case, then this is not like RBO, since that's not required. So is th=
is required or is it not?<br></div></blockquote><div>My mistake, I meant co=
py elision, not RVO. It is required.<br>=C2=A0<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"></blockquote><div>No. Stop using attributes to solve problems. <i=
>Especially</i> this one.<br></div></div></blockquote><div>Isn't that e=
xactly why attributes are there?<br>Note that the attribute has no influenc=
e on the optimization or similar, it will be performed anyway.<br>The attri=
bute just warns if the optimization cannot be performed.<br>There are alrea=
dy similar GCC/Clang attributes.<br>=C2=A0<br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div>You're essentially trying t=
o define away the problem by making the object not actually be a member. It=
's an interesting solution to the problem, but I don't think it'=
;s the best way to handle it.</div></div></blockquote><div>Yes, that's =
my idea. <br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/ef370ae4-4e1e-4370-8cd1-1f812c7473b1%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ef370ae4-4e1e-4370-8cd1-1f812c7473b1=
%40isocpp.org</a>.<br />
------=_Part_4533_1312009939.1467905871591--
------=_Part_4532_319656666.1467905871590--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 7 Jul 2016 09:15:52 -0700 (PDT)
Raw View
------=_Part_2279_1338981459.1467908152160
Content-Type: multipart/alternative;
boundary="----=_Part_2280_1557562119.1467908152160"
------=_Part_2280_1557562119.1467908152160
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, July 7, 2016 at 11:37:52 AM UTC-4, Jonathan M=C3=BCller wrote:
>
>
> On Thursday, July 7, 2016 at 4:22:46 PM UTC+2, Nicol Bolas wrote:
>
>> Why do people keep talking about this in terms of EBO, like that's the=
=20
>> only reason why you would ever want a member to take up no space?
>>
> No, because that's the only way to have empty members.
> So every solution would be a replacement for EBO.
>
No, it isn't.
EBO exists to permit optimized storage of base classes. Now, people have=20
used a type as a base class in cases that they otherwise would have just=20
used an NSDM *because* EBO is available. But that's not the only reason we=
=20
have EBO.
Stateless members do not replace EBO. It will replace using EBO for types=
=20
that you *want* to be members but can't due to overhead. When the=20
relationship between the subobject and its container is not an "is a"=20
relationship.
EBO will still be used for CRTP purposes, since that does model the "is a"=
=20
relationship.
=20
> So, a member function which calls a sibling member function that doesn't=
=20
>> access NSDMs wouldn't be allowed? That's a pretty harsh requirement. And=
a=20
>> very unnecessary one.
>>
> Many negations, let me grasp this:
> A member function that calls a sibling member function.
> The sibling member function doesn't access NSDMS, thus it is implictly=20
> static.
> And thus the original member function is implictly static.
>
And what if the two functions recursively call each other?
=20
> =20
>
>> And what if the type has its own member which is empty by this=20
>> definition? Are you saying that nested empty members don't work:
>>
>> struct Empty1 { void DoSomething() {}};
>> struct Empty2 {Empty 1 e; void DoSomething() {e.DoSomething();}};
>>
>> Why should `Empty2` not be just as empty as `Empty1`?
>>
> `Empty2` should be just as empty as `Empty1`, yes.
>
=20
>
>> Also, you are now doing something never before seen in C++: you are=20
>> changing the definition of a class based on the definition of one of its=
=20
>> member functions. Naturally that requires those member functions to be=
=20
>> inline. Consider this:
>>
>> struct Empty
>> {
>> void DoSomething();
>> };
>>
>> struct Full
>> {
>> int foo;
>> Empty bar;
>> };
>>
>> You are saying that `sizeof(Full)` depends on the eventual definition of=
=20
>> `DoSomething`. This means that compilers have to do one of the following=
:
>>
> No, because `Empty` doesn't have any member variables, `DoSomething`=20
> cannot possibly access any member variables and is thus implicitly static=
..
>
It can do this:
static Empty *ptr =3D nullptr;
void Empty::DoSomething()
{
ptr =3D this;
}
If `DoSomething` is a static function, then that code is il-formed. And=20
yet, that code is 100% legal and well-defined today. What you're proposing=
=20
would therefore break this code. While you might scoff at that for this=20
example, it would also break this code:
void Empty::DoSomething()
{
std::sort(..., [this](const auto &lhs, const auto &rhs) {...});
}
It would break any code where the function uses `this` as a=20
pointer/reference to its own instance. Empty types are passed by=20
pointer/reference quite frequently, and member functions of empty types=20
should reasonably be expected to be able to call such functions.
You cannot assume that member functions of empty classes don't use `this`.=
=20
Therefore, the only way to make your proposal work is to have the=20
determination of whether a type is stateless or not based on what its=20
member functions are actually doing. Based on their definitions. Which=20
means you need to *have those* definitions when it comes time to decide=20
what the class is.
You can't get around this. You cannot declare that stateless objects just *=
don't=20
exist*; they have to be real, live objects with actual, genuine pointers.
You said "will be". If that's the case, then this is not like RBO, since=20
>> that's not required. So is this required or is it not?
>>
> My mistake, I meant copy elision, not RVO. It is required.
>
Only partially; it is only required for non-named cases.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/449edd7a-b896-45cb-a64e-99940ff3d579%40isocpp.or=
g.
------=_Part_2280_1557562119.1467908152160
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, July 7, 2016 at 11:37:52 AM UTC-4, Jonathan M=
=C3=BCller wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><br>On Thursday, July 7, 2016 at 4:22:46 PM UTC+2, Nicol Bolas wrote:<b=
r><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"><div>Why do peop=
le keep talking about this in terms of EBO, like that's the only reason=
why you would ever want a member to take up no space?<br></div></div></blo=
ckquote><div>No, because that's the only way to have empty members.<br>=
So every solution would be a replacement for EBO.<br></div></div></blockquo=
te><div><br>No, it isn't.<br><br>EBO exists to permit optimized storage=
of base classes. Now, people have used a type as a base class in cases tha=
t they otherwise would have just used an NSDM <i>because</i> EBO is availab=
le. But that's not the only reason we have EBO.<br><br>Stateless member=
s do not replace EBO. It will replace using EBO for types that you <i>want<=
/i> to be members but can't due to overhead. When the relationship betw=
een the subobject and its container is not an "is a" relationship=
..<br><br>EBO will still be used for CRTP purposes, since that does model th=
e "is a" relationship.<br>=C2=A0</div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr">So, a member function which calls a sibling mem=
ber function that doesn't access NSDMs wouldn't be allowed? That=
9;s a pretty harsh requirement. And a very unnecessary one.<br></div></bloc=
kquote><div>Many negations, let me grasp this:<br>A member function that ca=
lls a sibling member function.<br>The sibling member function doesn't a=
ccess NSDMS, thus it is implictly static.<br>And thus the original member f=
unction is implictly static.<br></div></div></blockquote><div><br>And what =
if the two functions recursively call each other?<br>=C2=A0</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=C2=A0</div><div><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>And what=
if the type has its own member which is empty by this definition? Are you =
saying that nested empty members don't work:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#=
008">struct</span><span style=3D"color:#000"> </span><span style=3D"color:#=
606">Empty1</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#008">=
void</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Do=
Something</span><span style=3D"color:#660">()</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">{}};</span><span style=3D"color:#000=
"><br></span><span style=3D"color:#008">struct</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">Empty2</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#606">=
Empty</span><span style=3D"color:#000"> </span><span style=3D"color:#066">1=
</span><span style=3D"color:#000"> e</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">void</span=
><span style=3D"color:#000"> </span><span style=3D"color:#606">DoSomething<=
/span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000">e</span><sp=
an style=3D"color:#660">.</span><span style=3D"color:#606">DoSomething</spa=
n><span style=3D"color:#660">();}};</span></div></code></div><br>Why should=
`Empty2` not be just as empty as `Empty1`?<br></div></div></blockquote><di=
v>`Empty2` should be just as empty as `Empty1`, yes.<br></div></div></block=
quote><div></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><div>Also, you are now doing something never before seen in C++: you are=
changing the definition of a class based on the definition of one of its m=
ember functions. Naturally that requires those member functions to be inlin=
e. Consider this:<br><br><div style=3D"background-color:rgb(250,250,250);bo=
rder-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:b=
reak-word"><code><div><span style=3D"color:#008">struct</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Empty</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">void</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">DoSomething</spa=
n><span style=3D"color:#660">();</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">};</span><span style=3D"color:#000"><br><br></=
span><span style=3D"color:#008">struct</span><span style=3D"color:#000"> </=
span><span style=3D"color:#606">Full</span><span style=3D"color:#000"><br><=
/span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 </span><span style=3D"color:#008">int</span><span style=3D"color:#000">=
foo</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><b=
r>=C2=A0 </span><span style=3D"color:#606">Empty</span><span style=3D"color=
:#000"> bar</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br></span><span style=3D"color:#660">};</span></div></code></div><br>=
You are saying that `sizeof(Full)` depends on the eventual definition of `D=
oSomething`. This means that compilers have to do one of the following:<br>=
</div></div></blockquote><div>No, because `Empty` doesn't have any memb=
er variables, `DoSomething` cannot possibly access any member variables and=
is thus implicitly static.<br></div></div></blockquote><div><br>It can do =
this:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250,=
250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-w=
idth: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"></span><span style=3D"color: #008;" class=3D"styled-by-prettify"><code c=
lass=3D"prettyprint"><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">static</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Empty</sp=
an><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">ptr </span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">nullptr</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br><br></span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"></span></code>void</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">Empty</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span><span style=3D"color: #606;" class=3D"styled-by-prettify">DoSomet=
hing</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 ptr </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">this</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span></div></code></div><br>If `DoSomething` is a stat=
ic function, then that code is il-formed. And yet, that code is 100% legal =
and well-defined today. What you're proposing would therefore break thi=
s code. While you might scoff at that for this example, it would also break=
this code:<br><br><div class=3D"prettyprint" style=3D"background-color: rg=
b(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bo=
rder-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div c=
lass=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Empty</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">DoSomething</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 std</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">sort</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(...,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">[</span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>this</span><span style=3D"color: #660;" class=3D"styled-by-prettify">](</s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">lhs</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">const</span><span style=3D"color: #000;" 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"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">rhs</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{...});</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">}</span></div></code></div><br>It would break any code where the =
function uses `this` as a pointer/reference to its own instance. Empty type=
s are passed by pointer/reference quite frequently, and member functions of=
empty types should reasonably be expected to be able to call such function=
s.<br><br>You cannot assume that member functions of empty classes don'=
t use `this`. Therefore, the only way to make your proposal work is to have=
the determination of whether a type is stateless or not based on what its =
member functions are actually doing. Based on their definitions. Which mean=
s you need to <i>have those</i> definitions when it comes time to decide wh=
at the class is.<br><br>You can't get around this. You cannot declare t=
hat stateless objects just <i>don't exist</i>; they have to be real, li=
ve objects with actual, genuine pointers.<br><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr">You said "will be". If that=
9;s the case, then this is not like RBO, since that's not required. So =
is this required or is it not?<br></div></blockquote><div>My mistake, I mea=
nt copy elision, not RVO. It is required.<br></div></div></blockquote><div>=
<br>Only partially; it is only required for non-named cases.</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/449edd7a-b896-45cb-a64e-99940ff3d579%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/449edd7a-b896-45cb-a64e-99940ff3d579=
%40isocpp.org</a>.<br />
------=_Part_2280_1557562119.1467908152160--
------=_Part_2279_1338981459.1467908152160--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Thu, 7 Jul 2016 17:49:49 -0400
Raw View
--089e013d1c64577056053712aac0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thu, Jul 7, 2016 at 5:03 AM, Jonathan M=C3=BCller <
jonathanmueller.dev@gmail.com> wrote:
> This is a suggestion for a different approach to "solve" EBO.
> Responses to Allow zero size arrays and let them occupy zero bytes
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/51e6aec9-a7=
45-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> mentioned that the C++ object model cannot have anything that has size 0.
> So I got a completely different idea based on the fact that empty types
> are only needed for their member functions.
>
> 1. (optional, required for current empty types to work) Make member
> functions that don't access any non-static member variables or functio=
ns
> implicitly static.
>
>
This breaks existing ABIs. Lots of code breakage. Very bad, "...negative,
negative. We had a reactor leak here now... Large leak, very dangerous..."
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAOHCbiv0xArNXGUL7TWZTaTiy0jyysmL6Ak1Z5pJixZfvrU=
ZMA%40mail.gmail.com.
--089e013d1c64577056053712aac0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Thu, Jul 7, 2016 at 5:03 AM, Jonathan M=C3=BCller <span dir=3D"ltr">=
<<a href=3D"mailto:jonathanmueller.dev@gmail.com" target=3D"_blank">jona=
thanmueller.dev@gmail.com</a>></span> wrote:<br><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,2=
04,204);padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
This is a suggestion for a different approach to "solve" EBO.=
<br>
Responses to <a href=3D"https://groups.google.com/a/isocpp.org/d/msgid/=
std-proposals/51e6aec9-a745-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=
=3Demail&utm_source=3Dfooter" target=3D"_blank">Allow
zero size arrays and let them occupy zero bytes</a> mentioned that
the C++ object model cannot have anything that has size 0.<br>
So I got a completely different idea based on the fact that empty
types are only needed for their member functions.<br>
<ol>
<li>(optional, required for current empty types to work) Make
member functions that don't access any non-static member
variables or functions implicitly static.<br></li></ol></div></bloc=
kquote><div><br></div><div>This breaks existing ABIs.=C2=A0 Lots of code br=
eakage. Very bad,=C2=A0 "...negative, negative. We had a reactor leak =
here now... Large leak, very dangerous..."<br></div></div><br></div></=
div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAOHCbiv0xArNXGUL7TWZTaTiy0jyysmL6Ak1=
Z5pJixZfvrUZMA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOHCbiv0xArNXGUL=
7TWZTaTiy0jyysmL6Ak1Z5pJixZfvrUZMA%40mail.gmail.com</a>.<br />
--089e013d1c64577056053712aac0--
.
Author: arthur.odwyer@mixpanel.com
Date: Thu, 7 Jul 2016 17:19:38 -0700 (PDT)
Raw View
------=_Part_4836_1853285.1467937178173
Content-Type: multipart/alternative;
boundary="----=_Part_4837_679087117.1467937178174"
------=_Part_4837_679087117.1467937178174
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, July 7, 2016 at 2:03:52 AM UTC-7, Jonathan M=C3=BCller wrote:
>
> This is a suggestion for a different approach to "solve" EBO.
> Responses to Allow zero size arrays and let them occupy zero bytes=20
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/51e6aec9-a7=
45-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>=20
> mentioned that the C++ object model cannot have anything that has size 0.
> So I got a completely different idea based on the fact that empty types=
=20
> are only needed for their member functions.
>
> 1. (optional, required for current empty types to work) Make member=20
> functions that don't access any non-static member variables or functio=
ns=20
> implicitly static.
> This shouldn't break any existing code because you can call a static=
=20
> member function with the same syntax as a non-member function, so any =
code=20
> calling a member function can also call a static function without chan=
ge.
> =20
> As Nicol pointed out, this blows up on
struct A {
int not_visible();
int not_sure_if_implicitly_static_or_not() { return not_visible(); }
};
but my first thought was actually that it blows up on
struct B {
int oops() { return 3; }
int oops() const { return 4; }
};
and for that matter on
struct B {
int implicitly_static() { return 3; }
};
template<class T>
auto sfinae(const T& t) -> decltype(t.implicitly_static())
{
return 3;
}
.... sfinae(B()) ...
> "Encourage" - like with the RVO - compilers to remove objects that are=
=20
only used to call static member functions.
> Of course once the actual object is required (i.e. if you take the=20
address of it), this optimization cannot happen.
As in the first example (struct A) above, this can't possibly work if there=
=20
are any not-currently-visible-in-this-TU member functions or non-member=20
friend functions. Which also means that moving a member function from a=20
header file to a .cpp file could break your struct type's ABI. Which is=20
horrible.
Optimizations that *require* a whole-program or link-time optimizer are=20
pretty much non-starters.
> 2. A new attribute: maybe_empty (or a completely different name). It=20
informs the compiler
> that a member could be empty for some type and warns if you write code=20
that requires its existence.
This second idea doesn't seem useful unless we also adopt your "make member=
=20
functions static" idea, which is a non-starter, as described above.
If that first idea could be made to work, then this maybe_empty /=20
do_not_rely_on_my_existence attribute idea seems nice; but given that the=
=20
first idea is dead, so is this second idea.
=E2=80=93Arthur
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/71a5f1f4-0483-41eb-a15b-1caa5735bc17%40isocpp.or=
g.
------=_Part_4837_679087117.1467937178174
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, July 7, 2016 at 2:03:52 AM UTC-7, Jonathan M=
=C3=BCller wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
This is a suggestion for a different approach to "solve" EBO.=
<br>
Responses to <a href=3D"https://groups.google.com/a/isocpp.org/d/msgid/=
std-proposals/51e6aec9-a745-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium=
=3Demail&utm_source=3Dfooter" target=3D"_blank" rel=3D"nofollow" onmous=
edown=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/51e6aec9-a745-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter';return true;" onclick=3D"this.href=3D&#=
39;https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/51e6aec9-a7=
45-4fd9-94f7-bdd78b5798ca%40isocpp.org?utm_medium\x3demail\x26utm_source\x3=
dfooter';return true;">Allow
zero size arrays and let them occupy zero bytes</a> mentioned that
the C++ object model cannot have anything that has size 0.<br>
So I got a completely different idea based on the fact that empty
types are only needed for their member functions.<br>
<ol>
<li>(optional, required for current empty types to work) Make
member functions that don't access any non-static member
variables or functions implicitly static.<br>
This shouldn't break any existing code because you can call a
static member function with the same syntax as a non-member
function, so any code calling a member function can also call a
static function without change.<br></li></ol></div></blockquote><di=
v>As Nicol pointed out, this blows up on</div><div><br></div><div class=3D"=
prettyprint" style=3D"background-color: rgb(250, 250, 250); border: 1px sol=
id rgb(187, 187, 187); word-wrap: break-word;"><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-p=
rettify"> A </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> not_v=
isible</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> not_sure_=
if_implicitly_static_or_not</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> not_visible</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">();</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">};</span></div></code></div><div><br></div><div>but=
my first thought was actually that it blows up on</div><div><br></div><div=
><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); =
border: 1px solid rgb(187, 187, 187); word-wrap: break-word;"><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;" cla=
ss=3D"styled-by-prettify"> B </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> oops</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
66;" class=3D"styled-by-prettify">3</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
oops</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-pre=
ttify">4</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">};</span></div></code></div></div>=
<div><br></div><div>and for that matter on</div><div><br></div><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border: 1px=
solid rgb(187, 187, 187); word-wrap: break-word;"><code class=3D"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> B </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> i=
mplicitly_static</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
66;" class=3D"styled-by-prettify">3</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">template</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> sfinae</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">const</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"> t</span><sp=
an 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: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">decltype</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">t</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">imp=
licitly_static</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">())</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #066;" class=3D"styled-by-prettify">3</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br><br></span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> sfinae</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">B<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">())</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">...</span></div></code></di=
v><div><br></div><div>=C2=A0> "Encourage" - like with the RVO =
- compilers to remove objects
that are only used to call static member functions.</div><div>> =
Of course
once the actual object is required (i.e. if you take the address
of it), this optimization cannot happen.</div><div><br></div><div>A=
s in the first example (<font face=3D"courier new, monospace">struct A</fon=
t>) above, this can't possibly work if there are any not-currently-visi=
ble-in-this-TU member functions or non-member friend functions. Which also =
means that moving a member function from a header file to a .cpp file could=
break your struct type's ABI. Which is horrible.</div><div>Optimizatio=
ns that <i>require</i> a whole-program or link-time optimizer are pretty mu=
ch non-starters.</div><div><br></div><div>> 2. A new attribute: <font fa=
ce=3D"courier new,monospace">maybe_empty<font face=3D"arial,sans-serif"> (o=
r a completely different name).
It informs the compiler</font></font></div><div><font face=3D"c=
ourier new,monospace"><font face=3D"arial,sans-serif">> that a member co=
uld be empty for
some type and warns if you write code that requires its
existence.</font></font></div><div><font face=3D"courier new,mo=
nospace"><font face=3D"arial,sans-serif"><br></font></font></div><div><font=
face=3D"courier new,monospace"><font face=3D"arial,sans-serif">This second=
idea doesn't seem useful unless we also adopt your "make member f=
unctions static" idea, which is a non-starter, as described above.</fo=
nt></font></div><div>If that first idea could be made to work, then this <f=
ont face=3D"courier new, monospace">maybe_empty</font> / <font face=3D"cour=
ier new, monospace">do_not_rely_on_my_existence</font> attribute idea seems=
nice; but given that the first idea is dead, so is this second idea.</div>=
<div><br></div><div><font face=3D"arial, sans-serif">=E2=80=93Arthur</font>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;">
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/71a5f1f4-0483-41eb-a15b-1caa5735bc17%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/71a5f1f4-0483-41eb-a15b-1caa5735bc17=
%40isocpp.org</a>.<br />
------=_Part_4837_679087117.1467937178174--
------=_Part_4836_1853285.1467937178173--
.