Topic: Improve [[no_unique_address]] - make addresses
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 22 Aug 2018 13:26:21 -0700 (PDT)
Raw View
------=_Part_2643_1290843772.1534969581266
Content-Type: multipart/alternative;
boundary="----=_Part_2644_968634472.1534969581266"
------=_Part_2644_968634472.1534969581266
Content-Type: text/plain; charset="UTF-8"
On Wednesday, August 22, 2018 at 3:54:52 PM UTC-4, Ivan G. wrote:
>
> Hello, this is not really a proposal but rather a bunch of questions.
>
> First, could standard attribute even enforce something, or attributes are
> simply not suitable for this, judging by the fact they are silently ignored
> in C++17?
>
> The idea is simple - if data members with [[no_unique_address]] are empty,
> their exact location doesn't matter, why not always assume them at the
> beginning of the class, essentially reusing its base address, in other
> words, `this` pointer?
>
Because that would require that the compiler put them there.
Also, you forget that `no_unique_address` is a request, not a requirement.
There's nothing stopping an implementation from ignoring it, even if the
type is actually empty. I personally wanted to see some rules on it, but
despite standard layout rules that enforce EBO, others disagreed that
similar rules for this feature were important.
If there are no rules in place to ensure `no_unique_address` is respected
in certain cases, or even to have the ability to check to see if a given
type respects the attribute, then there will be no way for you to write
portable code that can rely on such a conversion.
The attendant idea is to allow reinterpret_cast it back to the type which
> contains the data member with [[no_unique_address]], and use it for:
> 1. Emulating "properties" in more advanced manner
>
Yeah, I've thought about that, and it doesn't work. Or rather, it's not
enough.
When I last looked at the problem
<https://github.com/NicolBolas/Proposal-Ideas/blob/master/older/Mixins%2C%20Inner%2C%20and%20Stateless%20Classess.md>,
I determined that a general "properties" feature done piecemeal required
three things:
1. A way to make empty members take up no storage in their containing
types. [[no_unique_address]] is inadequate to this, due to not having
enforceable rules.
2. A way to declare a class as a Java-style "inner class", such that
conversion from the contained class instance to the container instance was
supported just like accessing members of base classes from a derived class.
Even with your (and my) suggested changes, your example code is too fragile.
Your `prop_x` is copyable, which makes sense, as you want your outer `base`
type to be copyable. But if you can copy it, so can *users*. But they can't
use any of the copies, since that object *assumes* it is a
`no_unique_address`-declared member subobject of `base`. So they shouldn't
be able to copy it, but if it is non-copyable, then you need to write a
copy constructor/assignment operator that doesn't copy that member in order
to preserve your own stuff.
My notion of inner classes would fix that fragility. You can only construct
an inner class as a member subobject of the type it is an inner class for.
So the outer class is copyable, and the inner class is *technically*
copyable, but the compiler will fail if anyone tries to create such an
object as anything other than a member subobject of the proper type.
3. A way to provide the "guts" of the property implementation, irrespective
of where the variable it acts on its located (if there is a variable at
all). Note that your `prop_x` type needs to have intimate knowledge of
`base` and which variable it is attached to. Do you really want to rewrite
all of that code again and again for every property? What you want is to
put `set` and `get` functions inside the property class, and then generate
all of the necessary operators based on how you define those functions.
CRTP can do that, to an extent, but my notion of "mixins" (and Herb's *far
superior* notion of "metaclasses") handles this much better.
In the end, my idea would have allowed you to write your example as this
(using metaclass syntax, rather than my mixin idea):
class base
{
private:
int m_x;
public:
stateless inner class<std::property>
{
//Private members are OK; `property` is implicitly a friend.
const int &get() const {return m_x;}
//non-const reference means `property` will use this to set as well.
int &get() {return m_x;}
} x;
};
The `std::property` metaclass would read your members and generate
`operator=` and conversion operator functions based on them. If you didn't
provide a non-`const` version of `get`, then it wouldn't provide
`operator=` support. If you didn't provide any `get` at all, but provided a
single-argument, non-`const` `set`, then it would not provide conversion
operators, just `operator=`.
--
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/a18d7a1f-8868-4d11-b992-2ae10e99a60a%40isocpp.org.
------=_Part_2644_968634472.1534969581266
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 22, 2018 at 3:54:52 PM UTC-4, Ivan G.=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Hello,=
this is not really a proposal but rather a bunch of questions.<div><br></d=
iv><div>First, could standard attribute even enforce something, or attribut=
es are simply not suitable for this, judging by the fact they are silently =
ignored in C++17?</div><div><br></div><div>The idea is simple - if data mem=
bers with [[no_unique_address]] are empty, their exact location doesn't=
matter, why not always assume them at the beginning of the class, essentia=
lly reusing its base address, in other words, `this` pointer?</div></div></=
blockquote><div><br></div><div>Because that would require that the compiler=
put them there.</div><div><br></div><div>Also, you forget that `no_unique_=
address` is a request, not a requirement. There's nothing stopping an i=
mplementation from ignoring it, even if the type is actually empty. I perso=
nally wanted to see some rules on it, but despite standard layout rules tha=
t enforce EBO, others disagreed that similar rules for this feature were im=
portant.</div><div><br></div><div>If there are no rules in place to ensure =
`no_unique_address` is respected in certain cases, or even to have the abil=
ity to check to see if a given type respects the attribute, then there will=
be no way for you to write portable code that can rely on such a conversio=
n.<br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><div></div><div>The attendant idea is to allow reinterpret_ca=
st it back to the type which contains the data member with [[no_unique_addr=
ess]], and use it for:</div><div>1. Emulating "properties" in mor=
e advanced manner</div></div></blockquote><div><br></div><div>Yeah, I'v=
e thought about that, and it doesn't work. Or rather, it's not enou=
gh.</div><div><br></div><div>When <a href=3D"https://github.com/NicolBolas/=
Proposal-Ideas/blob/master/older/Mixins%2C%20Inner%2C%20and%20Stateless%20C=
lassess.md">I last looked at the problem</a>, I determined that a general &=
quot;properties" feature done piecemeal required three things:</div><d=
iv><br></div><div>1. A way to make empty members take up no storage in thei=
r containing types. [[no_unique_address]] is inadequate to this, due to not=
having enforceable rules.</div><div><br></div><div>2. A way to declare a c=
lass as a Java-style "inner class", such that conversion from the=
contained class instance to the container instance was supported just like=
accessing members of base classes from a derived class. Even with your (an=
d my) suggested changes, your example code is too fragile.</div><div><br></=
div><div>Your `prop_x` is copyable, which makes sense, as you want your out=
er `base` type to be copyable. But if you can copy it, so can <i>users</i>.=
But they can't use any of the copies, since that object <i>assumes</i>=
it is a `no_unique_address`-declared member subobject of `base`. So they s=
houldn't be able to copy it, but if it is non-copyable, then you need t=
o write a copy constructor/assignment operator that doesn't copy that m=
ember in order to preserve your own stuff.</div><div><br></div><div>My noti=
on of inner classes would fix that fragility. You can only construct an inn=
er class as a member subobject of the type it is an inner class for. So the=
outer class is copyable, and the inner class is <i>technically</i> copyabl=
e, but the compiler will fail if anyone tries to create such an object as a=
nything other than a member subobject of the proper type.<br></div><div><br=
></div><div>3. A way to provide the "guts" of the property implem=
entation, irrespective of where the variable it acts on its located (if the=
re is a variable at all). Note that your `prop_x` type needs to have intima=
te knowledge of `base` and which variable it is attached to. Do you really =
want to rewrite all of that code again and again for every property? What y=
ou want is to put `set` and `get` functions inside the property class, and =
then generate all of the necessary operators based on how you define those =
functions. CRTP can do that, to an extent, but my notion of "mixins&qu=
ot; (and Herb's <i>far superior</i> notion of "metaclasses") =
handles this much better.</div><div><br></div><div>In the end, my idea woul=
d have allowed you to write your example as this (using metaclass syntax, r=
ather than my mixin idea):</div><div><br></div><div style=3D"background-col=
or: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: sol=
id; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><c=
ode class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">base</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">pr=
ivate</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 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> m_x</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">public</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 stateless inner </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">property</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"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">//Private members are OK; `p=
roperty` is implicitly a friend.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">&</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">get</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">()</span><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 sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> m_x</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 =C2=A0 =C2=A0<br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-pretti=
fy">//non-const reference means `property` will use this to set as well.</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =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-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">get</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> m_x</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;}</span><span style=3D"color: #000;" class=3D"styl=
ed-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"style=
d-by-prettify"> x</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=
></div></code></div><div><br></div>The `std::property` metaclass would read=
your members and generate `operator=3D` and conversion operator functions =
based on them. If you didn't provide a non-`const` version of `get`, th=
en it wouldn't provide `operator=3D` support. If you didn't provide=
any `get` at all, but provided a single-argument, non-`const` `set`, then =
it would not provide conversion operators, just `operator=3D`.<br></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/a18d7a1f-8868-4d11-b992-2ae10e99a60a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a18d7a1f-8868-4d11-b992-2ae10e99a60a=
%40isocpp.org</a>.<br />
------=_Part_2644_968634472.1534969581266--
------=_Part_2643_1290843772.1534969581266--
.
Author: "Ivan G." <nekotekina@gmail.com>
Date: Fri, 24 Aug 2018 12:38:01 -0700 (PDT)
Raw View
------=_Part_400_398122049.1535139481271
Content-Type: multipart/alternative;
boundary="----=_Part_401_1096854218.1535139481272"
------=_Part_401_1096854218.1535139481272
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Thank you very much for the great explanation.
I understood the situation briefly.
This is a little sad, however - are the related proposals too incomplete,=
=20
or they just don't receive enough interest?
=D1=81=D1=80=D0=B5=D0=B4=D0=B0, 22 =D0=B0=D0=B2=D0=B3=D1=83=D1=81=D1=82=D0=
=B0 2018 =D0=B3., 23:26:21 UTC+3 =D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=
=D0=B0=D1=82=D0=B5=D0=BB=D1=8C Nicol Bolas =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=
=D0=B0=D0=BB:
>
> On Wednesday, August 22, 2018 at 3:54:52 PM UTC-4, Ivan G. wrote:
>>
>> Hello, this is not really a proposal but rather a bunch of questions.
>>
>> First, could standard attribute even enforce something, or attributes ar=
e=20
>> simply not suitable for this, judging by the fact they are silently igno=
red=20
>> in C++17?
>>
>> The idea is simple - if data members with [[no_unique_address]] are=20
>> empty, their exact location doesn't matter, why not always assume them a=
t=20
>> the beginning of the class, essentially reusing its base address, in oth=
er=20
>> words, `this` pointer?
>>
>
> Because that would require that the compiler put them there.
>
> Also, you forget that `no_unique_address` is a request, not a requirement=
..=20
> There's nothing stopping an implementation from ignoring it, even if the=
=20
> type is actually empty. I personally wanted to see some rules on it, but=
=20
> despite standard layout rules that enforce EBO, others disagreed that=20
> similar rules for this feature were important.
>
> If there are no rules in place to ensure `no_unique_address` is respected=
=20
> in certain cases, or even to have the ability to check to see if a given=
=20
> type respects the attribute, then there will be no way for you to write=
=20
> portable code that can rely on such a conversion.
>
> The attendant idea is to allow reinterpret_cast it back to the type which=
=20
>> contains the data member with [[no_unique_address]], and use it for:
>> 1. Emulating "properties" in more advanced manner
>>
>
> Yeah, I've thought about that, and it doesn't work. Or rather, it's not=
=20
> enough.
>
> When I last looked at the problem=20
> <https://github.com/NicolBolas/Proposal-Ideas/blob/master/older/Mixins%2C=
%20Inner%2C%20and%20Stateless%20Classess.md>,=20
> I determined that a general "properties" feature done piecemeal required=
=20
> three things:
>
> 1. A way to make empty members take up no storage in their containing=20
> types. [[no_unique_address]] is inadequate to this, due to not having=20
> enforceable rules.
>
> 2. A way to declare a class as a Java-style "inner class", such that=20
> conversion from the contained class instance to the container instance wa=
s=20
> supported just like accessing members of base classes from a derived clas=
s.=20
> Even with your (and my) suggested changes, your example code is too fragi=
le.
>
> Your `prop_x` is copyable, which makes sense, as you want your outer=20
> `base` type to be copyable. But if you can copy it, so can *users*. But=
=20
> they can't use any of the copies, since that object *assumes* it is a=20
> `no_unique_address`-declared member subobject of `base`. So they shouldn'=
t=20
> be able to copy it, but if it is non-copyable, then you need to write a=
=20
> copy constructor/assignment operator that doesn't copy that member in ord=
er=20
> to preserve your own stuff.
>
> My notion of inner classes would fix that fragility. You can only=20
> construct an inner class as a member subobject of the type it is an inner=
=20
> class for. So the outer class is copyable, and the inner class is=20
> *technically* copyable, but the compiler will fail if anyone tries to=20
> create such an object as anything other than a member subobject of the=20
> proper type.
>
> 3. A way to provide the "guts" of the property implementation,=20
> irrespective of where the variable it acts on its located (if there is a=
=20
> variable at all). Note that your `prop_x` type needs to have intimate=20
> knowledge of `base` and which variable it is attached to. Do you really=
=20
> want to rewrite all of that code again and again for every property? What=
=20
> you want is to put `set` and `get` functions inside the property class, a=
nd=20
> then generate all of the necessary operators based on how you define thos=
e=20
> functions. CRTP can do that, to an extent, but my notion of "mixins" (and=
=20
> Herb's *far superior* notion of "metaclasses") handles this much better.
>
> In the end, my idea would have allowed you to write your example as this=
=20
> (using metaclass syntax, rather than my mixin idea):
>
> class base
> {
> private:
> int m_x;
> public:
>
> stateless inner class<std::property>
> {
> //Private members are OK; `property` is implicitly a friend.
> const int &get() const {return m_x;}
> =20
> //non-const reference means `property` will use this to set as=20
> well.
> int &get() {return m_x;}
> } x;
> };
>
> The `std::property` metaclass would read your members and generate=20
> `operator=3D` and conversion operator functions based on them. If you did=
n't=20
> provide a non-`const` version of `get`, then it wouldn't provide=20
> `operator=3D` support. If you didn't provide any `get` at all, but provid=
ed a=20
> single-argument, non-`const` `set`, then it would not provide conversion=
=20
> operators, just `operator=3D`.
>
--=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/2a92b5d5-8b0e-4e5a-acf6-7da793f19aae%40isocpp.or=
g.
------=_Part_401_1096854218.1535139481272
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Thank you very much for the great explanation.<br></d=
iv><div>I understood the situation briefly.</div><div>This is a little sad,=
however - are the related proposals too incomplete, or they just don't=
receive enough interest?</div><br>=D1=81=D1=80=D0=B5=D0=B4=D0=B0, 22 =D0=
=B0=D0=B2=D0=B3=D1=83=D1=81=D1=82=D0=B0 2018 =D0=B3., 23:26:21 UTC+3 =D0=BF=
=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8C Nicol Bo=
las =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB:<blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr">On Wednesday, August 22, 2018 at 3:54:52 =
PM UTC-4, Ivan G. wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D=
"ltr">Hello, this is not really a proposal but rather a bunch of questions.=
<div><br></div><div>First, could standard attribute even enforce something,=
or attributes are simply not suitable for this, judging by the fact they a=
re silently ignored in C++17?</div><div><br></div><div>The idea is simple -=
if data members with [[no_unique_address]] are empty, their exact location=
doesn't matter, why not always assume them at the beginning of the cla=
ss, essentially reusing its base address, in other words, `this` pointer?</=
div></div></blockquote><div><br></div><div>Because that would require that =
the compiler put them there.</div><div><br></div><div>Also, you forget that=
`no_unique_address` is a request, not a requirement. There's nothing s=
topping an implementation from ignoring it, even if the type is actually em=
pty. I personally wanted to see some rules on it, but despite standard layo=
ut rules that enforce EBO, others disagreed that similar rules for this fea=
ture were important.</div><div><br></div><div>If there are no rules in plac=
e to ensure `no_unique_address` is respected in certain cases, or even to h=
ave the ability to check to see if a given type respects the attribute, the=
n there will be no way for you to write portable code that can rely on such=
a conversion.<br></div><div><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><div>The attendant idea is to allow reinterpret_cast i=
t back to the type which contains the data member with [[no_unique_address]=
], and use it for:</div><div>1. Emulating "properties" in more ad=
vanced manner</div></div></blockquote><div><br></div><div>Yeah, I've th=
ought about that, and it doesn't work. Or rather, it's not enough.<=
/div><div><br></div><div>When <a href=3D"https://github.com/NicolBolas/Prop=
osal-Ideas/blob/master/older/Mixins%2C%20Inner%2C%20and%20Stateless%20Class=
ess.md" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FNicolBolas%2FPro=
posal-Ideas%2Fblob%2Fmaster%2Folder%2FMixins%252C%2520Inner%252C%2520and%25=
20Stateless%2520Classess.md\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE-WT1Tz=
VqcqWw8JlMsGHz1AQ7tHg';return true;" onclick=3D"this.href=3D'https:=
//www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FNicolBolas%2FProposal-=
Ideas%2Fblob%2Fmaster%2Folder%2FMixins%252C%2520Inner%252C%2520and%2520Stat=
eless%2520Classess.md\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE-WT1TzVqcqWw=
8JlMsGHz1AQ7tHg';return true;">I last looked at the problem</a>, I dete=
rmined that a general "properties" feature done piecemeal require=
d three things:</div><div><br></div><div>1. A way to make empty members tak=
e up no storage in their containing types. [[no_unique_address]] is inadequ=
ate to this, due to not having enforceable rules.</div><div><br></div><div>=
2. A way to declare a class as a Java-style "inner class", such t=
hat conversion from the contained class instance to the container instance =
was supported just like accessing members of base classes from a derived cl=
ass. Even with your (and my) suggested changes, your example code is too fr=
agile.</div><div><br></div><div>Your `prop_x` is copyable, which makes sens=
e, as you want your outer `base` type to be copyable. But if you can copy i=
t, so can <i>users</i>. But they can't use any of the copies, since tha=
t object <i>assumes</i> it is a `no_unique_address`-declared member subobje=
ct of `base`. So they shouldn't be able to copy it, but if it is non-co=
pyable, then you need to write a copy constructor/assignment operator that =
doesn't copy that member in order to preserve your own stuff.</div><div=
><br></div><div>My notion of inner classes would fix that fragility. You ca=
n only construct an inner class as a member subobject of the type it is an =
inner class for. So the outer class is copyable, and the inner class is <i>=
technically</i> copyable, but the compiler will fail if anyone tries to cre=
ate such an object as anything other than a member subobject of the proper =
type.<br></div><div><br></div><div>3. A way to provide the "guts"=
of the property implementation, irrespective of where the variable it acts=
on its located (if there is a variable at all). Note that your `prop_x` ty=
pe needs to have intimate knowledge of `base` and which variable it is atta=
ched to. Do you really want to rewrite all of that code again and again for=
every property? What you want is to put `set` and `get` functions inside t=
he property class, and then generate all of the necessary operators based o=
n how you define those functions. CRTP can do that, to an extent, but my no=
tion of "mixins" (and Herb's <i>far superior</i> notion of &q=
uot;metaclasses") handles this much better.</div><div><br></div><div>I=
n the end, my idea would have allowed you to write your example as this (us=
ing metaclass syntax, rather than my mixin idea):</div><div><br></div><div =
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code><div><span style=3D"color:#008">cl=
ass</span><span style=3D"color:#000"> </span><span style=3D"color:#008">bas=
e</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br></span><span style=3D"color:#008">priv=
ate</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">int</span><span style=3D"c=
olor:#000"> m_x</span><span style=3D"color:#660">;</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#008">public</span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 statel=
ess inner </span><span style=3D"color:#008">class</span><span style=3D"colo=
r:#660"><</span><span style=3D"color:#000">std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#000">property</span><span style=3D"c=
olor:#660">></span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#800">//Private members are O=
K; `property` is implicitly a friend.</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const</span><=
span style=3D"color:#000"> </span><span style=3D"color:#008">int</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">&</span><span=
style=3D"color:#008">get</span><span style=3D"color:#660">()</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#008">const</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> m_x</span><span st=
yle=3D"color:#660">;}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#8=
00">//non-const reference means `property` will use this to set as well.</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span=
style=3D"color:#008">int</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">&</span><span style=3D"color:#008">get</span><span s=
tyle=3D"color:#660">()</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> m_x</span><span style=3D"color:#660">;}</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span=
><span style=3D"color:#000"> x</span><span style=3D"color:#660">;</span><sp=
an style=3D"color:#000"><br></span><span style=3D"color:#660">};</span></di=
v></code></div><div><br></div>The `std::property` metaclass would read your=
members and generate `operator=3D` and conversion operator functions based=
on them. If you didn't provide a non-`const` version of `get`, then it=
wouldn't provide `operator=3D` support. If you didn't provide any =
`get` at all, but provided a single-argument, non-`const` `set`, then it wo=
uld not provide conversion operators, just `operator=3D`.<br></div></blockq=
uote></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/2a92b5d5-8b0e-4e5a-acf6-7da793f19aae%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2a92b5d5-8b0e-4e5a-acf6-7da793f19aae=
%40isocpp.org</a>.<br />
------=_Part_401_1096854218.1535139481272--
------=_Part_400_398122049.1535139481271--
.