Topic: extend_cast<T> : extending interfaces safely


Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 25 Jul 2017 18:37:13 -0700
Raw View
On ter=C3=A7a-feira, 25 de julho de 2017 17:47:38 PDT Tahsin Mazumdar wrote=
:
> Currently there is no easy way to extend class interfaces and still remai=
n
> compatible with instances of the older interface. In certain cases, this
> might not be all that difficult to do if we ensure that the binary layout
> does not change across interfaces.
>=20
> Let's say as an arbitrary example we want to extend the std::vector
> interface, we could do the following:
>=20
> template <typename T>
> class extended_vector : public std::vector<T>
> {
> public:
>   template <typename... Args>
>   extended_vector(Args&&... args): std::vector<T>(std::forward<Args>(args
> )...) {}
>=20
>   auto accumulate(T init)
>   {
>     return std::accumulate(this->begin(), this->end(), init);
>   }
>=20
> };
>=20
> Note that since we have not added any member variables to extended_vector=
,
> the binary layout of the two classes should be identical.=20

The standard does not guarantee that. So from this point on, let's make the=
=20
assumption that only standard-layout classes can be layout identical.

std::vector may or may not be standard-layout.

> Thus, at least in
> concept, I should be able to use instances of either class interchangeabl=
y
> with the other's interface. However this is not the case: if I only have =
an
> instance of std::vector<T>, there is no standard way to "treat" that
> instance like an extended_vector<T> and take advantage of its extended
> interface.

Correct, because it isn't of that type. Casting to a type that the object=
=20
isn't is ill-formed.

> There might be another solution, simply to cast the std::vector as an
> extended_vector. Though this also has its problems currently:
>=20
> std::vector<int> A { 1,2,3,4};
> auto const& B =3D static_cast<extended_vector<int>&>(A);
> B.accumulate(2);
>=20
> This code compiles and works as expected.=20

Actually, "as expected" is a matter of opinion. Since it is incorrect, some=
one=20
could have a different opinion than yours.

> To get around this problem I wonder if it might be possible to introduce =
a
> new form of cast that simply does a compile-time check to verify that the
> binary layout is the same. Essentially it could give a compile-error if t=
he
> binary layouts of the classes are not equivalent and only compile if we a=
re
> certain that the downcast conversion is safe. It could be as simple as
> checking that the extended interface does not define any additional state=
..
> If there is no additional state, only member functions (or possibly
> statics), any added functionality would live outside of the instance givi=
ng
> us no reason to expect any undefined behavior if we were to cast it to th=
e
> newer interface:

Again, since the standard does not talk about layout of a class except for=
=20
standard layout classes, this new form of casting would only be allowed in=
=20
standard layout classes too. Applying to other types could be allowed as an=
=20
extension by the compilers, but you can't use it portably then.

And you can't use it in std::vector because you don't know whether it's=20
standard layout or not.

> This feature would allow us to extend interfaces in C++ style, enabling
> better encapsulation and readability and encourage the use of classes and
> inheritance (and as a result better code reuse through access to
> 'protected' members of the base, which we would not get through free
> functions).

I'm not sure we want to encourage that. This kind of hack is just plain UB=
=20
today.

--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--=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/8250383.MOPs3aM9AG%40tjmaciei-mobl1.

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 25 Jul 2017 18:53:17 -0700 (PDT)
Raw View
------=_Part_4647_1031332760.1501033997209
Content-Type: multipart/alternative;
 boundary="----=_Part_4648_102039039.1501033997210"

------=_Part_4648_102039039.1501033997210
Content-Type: text/plain; charset="UTF-8"

On Tuesday, July 25, 2017 at 8:47:38 PM UTC-4, Tahsin Mazumdar wrote:
>
> The standard library does this to a great extent for extending interfaces
> (i.e. writing free functions). But this is not an ideal solution in my
> opinion as it breaks encapsulation to a certain degree - related data and
> functions should be coupled together. std::accumulate operates primarily on
> the state defined inside of vector; to have them be separate forces us to
> pass in every member needed individually (e.g. begin() and end()) and
> results in cumbersome and longer syntax as we see with the <algorithm>
> library. This also discourages the use of classes and inheritance entirely
> when we are looking to scale up. From a design perspective, it forces
> developers to adopt a mix of C style (use of free functions) and
> Object-Oriented C++ style (classes and member functions) for a relatively
> mundane reason.
>

This is the fundamental foundation of your entire argument. You want this
feature because you believe what you said to be the way C++ code ought to
be done.

But it's not workable.

Let's take your feature at face value. Let's say we implement it and make
it work as you want it to. And let's say we define some
`std::algorithm_vector`, which implements every C++ function in the
<algorithm> header as a member function.

So, first question: how do I accumulate only *part* of a vector?

Second question: what happens if I want to create *new* algorithms?
Algorithms that ought to be able to work with any container. You wouldn't
be able to directly use `std::algorithm_vector` members, since they won't
be members of that type. You'll have to either create some
`my::new_algorithm_vector` type or just use non-member functions.

So even if we have this feature, you're *still* going to need those
non-member functions. And if that's the case... what's the point of this
feature?

These are the kinds of problems you come upon when you start treating
member functions and inheritance as "The One True Way", rather than "useful
where it's useful." There are many tools in C++ for extending the
capability of types; you're doing yourself and the language a disservice by
trying to fit everything into one little box.

So before this can be entertained further, I say that it needs better
motivations than "C++ isn't OOP enough for me."

--
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/1067a585-20dc-4388-9299-baba8161ef49%40isocpp.org.

------=_Part_4648_102039039.1501033997210
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, July 25, 2017 at 8:47:38 PM UTC-4, Tahsin Mazu=
mdar 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">Th=
e standard library does this to a great extent for extending interfaces (i.=
e. writing free functions). But this is not an ideal solution in my opinion=
 as it breaks encapsulation=20
to a certain degree - related data and functions should be coupled=20
together. std::accumulate operates primarily on the state defined inside of=
 vector; to have them be separate forces us to pass in every member needed =
individually (e.g. begin() and
 end()) and results in cumbersome and longer syntax as we see with the=20
&lt;algorithm&gt; library. This also discourages the use of classes and inh=
eritance entirely when we
 are looking to scale up. From a design perspective, it forces developers t=
o adopt a mix of C style (use of free functions) and Object-Oriented C++ st=
yle (classes and member functions) for a relatively mundane reason.<br></di=
v></blockquote><div><br>This is the fundamental foundation of your entire a=
rgument. You want this feature because you believe what you said to be the =
way C++ code ought to be done.<br><br>But it&#39;s not workable.<br><br>Let=
&#39;s take your feature at face value. Let&#39;s say we implement it and m=
ake it work as you want it to. And let&#39;s say we define some `std::algor=
ithm_vector`, which implements every C++ function in the &lt;algorithm&gt; =
header as a member function.<br><br>So, first question: how do I accumulate=
 only <i>part</i> of a vector?<br><br>Second question: what happens if I wa=
nt to create <i>new</i> algorithms? Algorithms that ought to be able to wor=
k with any container. You wouldn&#39;t be able to directly use `std::algori=
thm_vector` members, since they won&#39;t be members of that type. You&#39;=
ll have to either create some `my::new_algorithm_vector` type or just use n=
on-member functions.<br><br>So even if we have this feature, you&#39;re <i>=
still</i> going to need those non-member functions. And if that&#39;s the c=
ase... what&#39;s the point of this feature?<br><br>These are the kinds of =
problems you come upon when you start treating member functions and inherit=
ance as &quot;The One True Way&quot;, rather than &quot;useful where it&#39=
;s useful.&quot; There are many tools in C++ for extending the capability o=
f types; you&#39;re doing yourself and the language a disservice by trying =
to fit everything into one little box.<br><br>So before this can be enterta=
ined further, I say that it needs better motivations than &quot;C++ isn&#39=
;t OOP enough for me.&quot;<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1067a585-20dc-4388-9299-baba8161ef49%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1067a585-20dc-4388-9299-baba8161ef49=
%40isocpp.org</a>.<br />

------=_Part_4648_102039039.1501033997210--

------=_Part_4647_1031332760.1501033997209--

.


Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 25 Jul 2017 21:31:09 -0500
Raw View
--001a113a13de0e7c9505552f40c5
Content-Type: text/plain; charset="UTF-8"

On Tue, Jul 25, 2017 at 7:47 PM, Tahsin Mazumdar <tahsin.tanzim@gmail.com>
wrote:

>
> To get around this problem I wonder if it might be possible to introduce a
> new form of cast that simply does a compile-time check to verify that the
> binary layout is the same.
>

The problem is that binary layout isn't sufficient.  Your derived class may
have a constructor that sets up a class invariant.  For instance:

struct B {
    explicit B(int i_ = 0) : i{i_} {}
    // ...
private:
    const int i;
};

struct D : B {
    D() : B{1} {}
    // ...
};

Casting an arbitrary instance of B to D would be wrong, since any and all
functions involving D can assume that i == 1.
--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  +1-847-691-1404

--
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/CAGg_6%2BM0vwGX7gAFN5znohn%3DR%3DNm4KZhi59AgNu_JcaDCxguug%40mail.gmail.com.

--001a113a13de0e7c9505552f40c5
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tue, Jul 25, 2017 at 7:47 PM, Tahsin Mazumdar <span dir=
=3D"ltr">&lt;<a href=3D"mailto:tahsin.tanzim@gmail.com" target=3D"_blank">t=
ahsin.tanzim@gmail.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra">=
<div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<br>To get around this problem I wonder if it might be possible to introduc=
e a new form of cast that simply does a compile-time check to verify that t=
he binary layout is the same.</div></blockquote><div><br></div><div>The pro=
blem is that binary layout isn&#39;t sufficient.=C2=A0 Your derived class m=
ay have a constructor that sets up a class invariant.=C2=A0 For instance:</=
div><div><br></div><div>struct B {</div><div>=C2=A0 =C2=A0 explicit B(int i=
_ =3D 0) : i{i_} {}<br></div><div>=C2=A0 =C2=A0 // ...</div><div>private:</=
div><div>=C2=A0 =C2=A0 const int i;</div><div>};</div><div><br></div><div>s=
truct D : B {</div><div>=C2=A0 =C2=A0 D() : B{1} {}</div><div>=C2=A0 =C2=A0=
 // ...</div><div>};</div><div><br></div><div>Casting an arbitrary instance=
 of B to D would be wrong, since any and all functions involving D can assu=
me that i =3D=3D 1.</div></div>-- <br><div class=3D"gmail_signature" data-s=
martmail=3D"gmail_signature"><div dir=3D"ltr"><div><div dir=3D"ltr"><div>=
=C2=A0Nevin &quot;:-)&quot; Liber=C2=A0 &lt;mailto:<a href=3D"mailto:nevin@=
eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&gt; =C2=A0+1=
-847-691-1404</div></div></div></div></div>
</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAGg_6%2BM0vwGX7gAFN5znohn%3DR%3DNm4K=
Zhi59AgNu_JcaDCxguug%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGg_6%2BM0=
vwGX7gAFN5znohn%3DR%3DNm4KZhi59AgNu_JcaDCxguug%40mail.gmail.com</a>.<br />

--001a113a13de0e7c9505552f40c5--

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Mon, 31 Jul 2017 17:55:47 -0400
Raw View
On 2017-07-25 20:47, Tahsin Mazumdar wrote:
> Currently there is no easy way to extend class interfaces and still remain
> compatible with instances of the older interface. In certain cases, this
> might not be all that difficult to do if we ensure that the binary layout
> does not change across interfaces.

Despite the nay-sayers, I think this feature would be useful. I'm pretty
sure I've run into this sort of thing, possibly even implemented the UB
mechanism. I think the issues that were raised could be solved by the
extension class being explicitly that: some new class type that can't
exist on its own, but to which a "base" class can be casted.

The trouble is... I'm pretty sure the times I've needed this feature are
because I needed to break encapsulation of a class for some reason (for
example, access protected members of a class that was created outside my
control). Given that breaking encapsulation is the most compelling use
case, I'm not sure that's something we want to standardize...

For the cases where it's merely convenient, I agree with the other
posters; I don't find mere convenience to be a sufficiently compelling
motivation.

--
Matthew

--
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/7969b5c2-4cfe-02b1-b320-5b88836e623a%40gmail.com.

.


Author: koczurekk@gmail.com
Date: Mon, 31 Jul 2017 16:59:39 -0700 (PDT)
Raw View
------=_Part_3965_158641476.1501545579585
Content-Type: multipart/alternative;
 boundary="----=_Part_3966_67583505.1501545579585"

------=_Part_3966_67583505.1501545579585
Content-Type: text/plain; charset="UTF-8"



On Wednesday, 26 July 2017 03:53:17 UTC+2, Nicol Bolas wrote:
>
> On Tuesday, July 25, 2017 at 8:47:38 PM UTC-4, Tahsin Mazumdar wrote:
>>
>> The standard library does this to a great extent for extending interfaces
>> (i.e. writing free functions). But this is not an ideal solution in my
>> opinion as it breaks encapsulation to a certain degree - related data and
>> functions should be coupled together. std::accumulate operates primarily on
>> the state defined inside of vector; to have them be separate forces us to
>> pass in every member needed individually (e.g. begin() and end()) and
>> results in cumbersome and longer syntax as we see with the <algorithm>
>> library. This also discourages the use of classes and inheritance entirely
>> when we are looking to scale up. From a design perspective, it forces
>> developers to adopt a mix of C style (use of free functions) and
>> Object-Oriented C++ style (classes and member functions) for a relatively
>> mundane reason.
>>
>
> This is the fundamental foundation of your entire argument. You want this
> feature because you believe what you said to be the way C++ code ought to
> be done.
>
> But it's not workable.
>
> Let's take your feature at face value. Let's say we implement it and make
> it work as you want it to. And let's say we define some
> `std::algorithm_vector`, which implements every C++ function in the
> <algorithm> header as a member function.
>
> So, first question: how do I accumulate only *part* of a vector?
>
> Second question: what happens if I want to create *new* algorithms?
> Algorithms that ought to be able to work with any container. You wouldn't
> be able to directly use `std::algorithm_vector` members, since they won't
> be members of that type. You'll have to either create some
> `my::new_algorithm_vector` type or just use non-member functions.
>
> So even if we have this feature, you're *still* going to need those
> non-member functions. And if that's the case... what's the point of this
> feature?
>
> These are the kinds of problems you come upon when you start treating
> member functions and inheritance as "The One True Way", rather than "useful
> where it's useful." There are many tools in C++ for extending the
> capability of types; you're doing yourself and the language a disservice by
> trying to fit everything into one little box.
>
> So before this can be entertained further, I say that it needs better
> motivations than "C++ isn't OOP enough for me."
>
While I agree that his reasoning wasn't quite correct, I like the outcome.
Stuff in <algorithm> is there for a reason, but extend_cast<T> would be
quite useful in some cases. Let's say that I'm implementing a class
`Message` that's only purpose besides storing a string (what can be done
with `std::string`) is to split it into a `std::vector` of
`std::array<char, 256>` so that I could easily send it with
Boost.Interprocess (just an example, could be anything else). The ideal
solution would be to derive from `std::string` and add that method. It
would be code really easy to maintain, I could keep all the `std::string`'s
features, constructors etc., just great. The only, sadly really big,
problem is casting. While I could just write a function to safely convert
those, it would result in more code, which in turn would cause my code to
be less maintainable.
extend_cast<T> would finally enable programmers write safe and maintainable
code while inheriting classes from `std::` namespace, which IMHO by now is
a really bad habit without language features like the discussed one.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/15f9d679-26aa-4fe1-a706-45dfc13c2075%40isocpp.org.

------=_Part_3966_67583505.1501545579585
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Wednesday, 26 July 2017 03:53:17 UTC+2, Nicol B=
olas  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">O=
n Tuesday, July 25, 2017 at 8:47:38 PM UTC-4, Tahsin Mazumdar wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">The standard library does=
 this to a great extent for extending interfaces (i.e. writing free functio=
ns). But this is not an ideal solution in my opinion as it breaks encapsula=
tion=20
to a certain degree - related data and functions should be coupled=20
together. std::accumulate operates primarily on the state defined inside of=
 vector; to have them be separate forces us to pass in every member needed =
individually (e.g. begin() and
 end()) and results in cumbersome and longer syntax as we see with the=20
&lt;algorithm&gt; library. This also discourages the use of classes and inh=
eritance entirely when we
 are looking to scale up. From a design perspective, it forces developers t=
o adopt a mix of C style (use of free functions) and Object-Oriented C++ st=
yle (classes and member functions) for a relatively mundane reason.<br></di=
v></blockquote><div><br>This is the fundamental foundation of your entire a=
rgument. You want this feature because you believe what you said to be the =
way C++ code ought to be done.<br><br>But it&#39;s not workable.<br><br>Let=
&#39;s take your feature at face value. Let&#39;s say we implement it and m=
ake it work as you want it to. And let&#39;s say we define some `std::algor=
ithm_vector`, which implements every C++ function in the &lt;algorithm&gt; =
header as a member function.<br><br>So, first question: how do I accumulate=
 only <i>part</i> of a vector?<br><br>Second question: what happens if I wa=
nt to create <i>new</i> algorithms? Algorithms that ought to be able to wor=
k with any container. You wouldn&#39;t be able to directly use `std::algori=
thm_vector` members, since they won&#39;t be members of that type. You&#39;=
ll have to either create some `my::new_algorithm_vector` type or just use n=
on-member functions.<br><br>So even if we have this feature, you&#39;re <i>=
still</i> going to need those non-member functions. And if that&#39;s the c=
ase... what&#39;s the point of this feature?<br><br>These are the kinds of =
problems you come upon when you start treating member functions and inherit=
ance as &quot;The One True Way&quot;, rather than &quot;useful where it&#39=
;s useful.&quot; There are many tools in C++ for extending the capability o=
f types; you&#39;re doing yourself and the language a disservice by trying =
to fit everything into one little box.<br><br>So before this can be enterta=
ined further, I say that it needs better motivations than &quot;C++ isn&#39=
;t OOP enough for me.&quot;<br></div></div></blockquote><div>While I agree =
that his reasoning wasn&#39;t quite correct, I like the outcome. Stuff in &=
lt;algorithm&gt; is there for a reason, but extend_cast&lt;T&gt; would be q=
uite useful in some cases. Let&#39;s say that I&#39;m implementing a class =
`Message` that&#39;s only purpose besides storing a string (what can be don=
e with `std::string`) is to split it into a `std::vector` of `std::array&lt=
;char, 256&gt;` so that I could easily send it with Boost.Interprocess (jus=
t an example, could be anything else). The ideal solution would be to deriv=
e from `std::string` and add that method. It would be code really easy to m=
aintain, I could keep all the `std::string`&#39;s features, constructors et=
c., just great. The only, sadly really big, problem is casting. While I cou=
ld just write a function to safely convert those, it would result in more c=
ode, which in turn would cause my code to be less maintainable.</div><div>e=
xtend_cast&lt;T&gt; would finally enable programmers write safe and maintai=
nable code while inheriting classes from `std::` namespace, which IMHO by n=
ow is a really bad habit without language features like the discussed one.<=
/div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/15f9d679-26aa-4fe1-a706-45dfc13c2075%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/15f9d679-26aa-4fe1-a706-45dfc13c2075=
%40isocpp.org</a>.<br />

------=_Part_3966_67583505.1501545579585--

------=_Part_3965_158641476.1501545579585--

.


Author: Michael Hava <mfh@live.at>
Date: Tue, 1 Aug 2017 02:35:36 -0700 (PDT)
Raw View
------=_Part_3175_392523417.1501580136309
Content-Type: multipart/alternative;
 boundary="----=_Part_3176_151683209.1501580136309"

------=_Part_3176_151683209.1501580136309
Content-Type: text/plain; charset="UTF-8"



Am Dienstag, 1. August 2017 01:59:39 UTC+2 schrieb kocz...@gmail.com:

> Let's say that I'm implementing a class `Message` that's only purpose
> besides storing a string (what can be done with `std::string`) is to split
> it into a `std::vector` of `std::array<char, 256>` so that I could easily
> send it with Boost.Interprocess (just an example, could be anything else).
>

I honestly don't see why this should be implemented as a member function,
when a free function dependent only on the public interface of std::string
would be sufficient...

--
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/9fbd3d46-f1f4-4945-b4fa-f0a8ad9b57e3%40isocpp.org.

------=_Part_3176_151683209.1501580136309
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>Am Dienstag, 1. August 2017 01:59:39 UTC+2 schrieb=
 kocz...@gmail.com:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr"><div>Let&#39;s say that I&#39;m implementing a class `Message` th=
at&#39;s only purpose besides storing a string (what can be done with `std:=
:string`) is to split it into a `std::vector` of `std::array&lt;char, 256&g=
t;` so that I could easily send it with Boost.Interprocess (just an example=
, could be anything else).</div></div></blockquote><div><br></div><div>I ho=
nestly don&#39;t see why this should be implemented as a member function, w=
hen a free function dependent only on the public interface of std::string w=
ould be sufficient...</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9fbd3d46-f1f4-4945-b4fa-f0a8ad9b57e3%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9fbd3d46-f1f4-4945-b4fa-f0a8ad9b57e3=
%40isocpp.org</a>.<br />

------=_Part_3176_151683209.1501580136309--

------=_Part_3175_392523417.1501580136309--

.


Author: p_hampson@wargaming.net
Date: Tue, 1 Aug 2017 05:03:31 -0700 (PDT)
Raw View
------=_Part_4909_121765100.1501589011664
Content-Type: multipart/alternative;
 boundary="----=_Part_4910_551532587.1501589011664"

------=_Part_4910_551532587.1501589011664
Content-Type: text/plain; charset="UTF-8"

On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:
>
> Currently there is no easy way to extend class interfaces and still remain
> compatible with instances of the older interface. In certain cases, this
> might not be all that difficult to do if we ensure that the binary layout
> does not change across interfaces.
>
>

I feel that the problem being solved (not liking the "free-function"
generic programming style currently encouraged by the STL) is something
like an opt-in version of half of "universal call syntax" (a.b(...) => b(a,
....)), and/or a specific use-case for operator., where the wrapper type
would have no state but the wrapped type.

On the other hand, the suggested solution (extend_cast) seems feasible now
using type traits, simply by having the cast template function
static_assert that the target inherits from the input, is standard_layout,
and is the same size. You could probably apply the static reflection work
to be absolutely sure that someone isn't casting down to a type that stows
something in the base class's padding, or otherwise messes with alignment
to fool the size check.


This feature would allow us to extend interfaces in C++ style, enabling
> better encapsulation and readability and encourage the use of classes and
> inheritance (and as a result better code reuse through access to
> 'protected' members of the base, which we would not get through free
> functions).
>

I think that 'protected' members might be intended precisely to disallow
things like this, so I'm not convinced 'better' is the right term here.
Certainly 'more' code-reuse, if we're talking about protected member
functions; 'less' code-reuse (and more risk to class invariants) if we're
talking about protected data members.

In the end, and it's a philosophical point, "encourage the use of classes
and inheritance" reads to me like "encourage the use of the letter a". It's
useful/powerful (or even "core", if you prefer), but you will be
sufficiently tooled for your development work irrespective of your level of
use in your code.

--
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/1c06961a-cf3a-4b68-8f68-95602be863f8%40isocpp.org.

------=_Part_4910_551532587.1501589011664
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin =
Mazumdar 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=
">Currently there is no easy way to extend class interfaces and still remai=
n compatible with instances of the older interface. In certain cases, this =
might not be all that difficult to do if we ensure that the binary layout d=
oes not change across interfaces.<br><br></div></blockquote><div>=C2=A0</di=
v><div><br></div><div>I feel that the problem being solved (not liking the =
&quot;free-function&quot; generic programming style currently encouraged by=
 the STL) is something like an opt-in version of half of &quot;universal ca=
ll syntax&quot; (<font face=3D"courier new, monospace">a.b(...) =3D&gt; b(a=
, ...)</font>), and/or a specific use-case for <font face=3D"courier new, m=
onospace">operator.</font>, where the wrapper type would have no state but =
the wrapped type.</div><div><br></div><div>On the other hand, the suggested=
 solution (<font face=3D"courier new, monospace">extend_cast</font>) seems =
feasible now using type traits, simply by having the cast template function=
 static_assert that the target inherits from the input, is standard_layout,=
 and is the same size. You could probably apply the static reflection work =
to be absolutely sure that someone isn&#39;t casting down to a type that st=
ows something in the base class&#39;s padding, or otherwise messes with ali=
gnment to fool the size check.</div><div><br></div><div><br></div><div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-le=
ft: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div dir=3D"ltr">This=
 feature would allow us to extend interfaces in C++ style, enabling better =
encapsulation and readability and encourage the use of classes and inherita=
nce (and as a result better code reuse through access to &#39;protected&#39=
; members of the base, which we would not get through free functions).=C2=
=A0<br></div></blockquote><div><br></div><div>I think that &#39;protected&#=
39; members might be intended precisely to disallow things like this, so I&=
#39;m not convinced &#39;better&#39; is the right term here. Certainly &#39=
;more&#39; code-reuse, if we&#39;re talking about protected member function=
s; &#39;less&#39; code-reuse (and more risk to class invariants) if we&#39;=
re talking about protected data members.</div></div><div><br></div><div>In =
the end, and it&#39;s a philosophical point, &quot;encourage the use of cla=
sses and inheritance&quot; reads to me like &quot;encourage the use of the =
letter a&quot;. It&#39;s useful/powerful (or even &quot;core&quot;, if you =
prefer), but you will be sufficiently tooled for your development work irre=
spective of your level of use in your code.</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1c06961a-cf3a-4b68-8f68-95602be863f8%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1c06961a-cf3a-4b68-8f68-95602be863f8=
%40isocpp.org</a>.<br />

------=_Part_4910_551532587.1501589011664--

------=_Part_4909_121765100.1501589011664--

.


Author: Ryan Nicholl <r.p.nicholl@gmail.com>
Date: Wed, 23 Aug 2017 16:52:47 -0700 (PDT)
Raw View
------=_Part_199_1686183263.1503532367402
Content-Type: multipart/alternative;
 boundary="----=_Part_200_110670975.1503532367403"

------=_Part_200_110670975.1503532367403
Content-Type: text/plain; charset="UTF-8"

I don't like the universal syntax. I think it adds too much complexity in
finding where methods are defined. What happens when foo.a() exists but
foo::a() does not? This is bound to be very confusing.

The extend-cast idea is very useful, but I think it needs some better
syntax. Here's my proposal (basically):

template <typename T, typename Alloc = std::default_allocator<T> >
class extended_vector
 : public &std::vector<T, Alloc>
{
  ...
public:
  void extra_member_function() { ... }
};



std::vector<int> vector_a;
auto && vector_extended = extend_cast<extended_vector<int> >(vector_a);
By inheriting from a reference we gain some advantages, it ensures that
there is no conversion between underlying data types (since it's just a
reference to the same data) but we get extra member functions and the
ability to use protected members of the base class.
Inheriting from an extended type could also be done using value semantics,
yet the underlying type would be a reference. This could be particularly
useful for overriding some member functions without proxying the entire
class.
Also, this could be useful for adding additional "phantom" or "ghost"
member variables. The ability to define a member variable on the "extended"
type would be useful. (They could be initialized in the constructor of the
class) Of course, you wouldn't be able to take a reference to a temporary
which means that you'd need the && syntax which could cause some issues
when forwarding? I'd say maybe just add an "auto(ghost)" keyword for this
type of variable.

On Tuesday, August 1, 2017 at 8:03:31 AM UTC-4, p_ha...@wargaming.net wrote:
>
> On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:
>>
>> Currently there is no easy way to extend class interfaces and still
>> remain compatible with instances of the older interface. In certain cases,
>> this might not be all that difficult to do if we ensure that the binary
>> layout does not change across interfaces.
>>
>>
>
> I feel that the problem being solved (not liking the "free-function"
> generic programming style currently encouraged by the STL) is something
> like an opt-in version of half of "universal call syntax" (a.b(...) =>
> b(a, ...)), and/or a specific use-case for operator., where the wrapper
> type would have no state but the wrapped type.
>
> On the other hand, the suggested solution (extend_cast) seems feasible
> now using type traits, simply by having the cast template function
> static_assert that the target inherits from the input, is standard_layout,
> and is the same size. You could probably apply the static reflection work
> to be absolutely sure that someone isn't casting down to a type that stows
> something in the base class's padding, or otherwise messes with alignment
> to fool the size check.
>
>
> This feature would allow us to extend interfaces in C++ style, enabling
>> better encapsulation and readability and encourage the use of classes and
>> inheritance (and as a result better code reuse through access to
>> 'protected' members of the base, which we would not get through free
>> functions).
>>
>
> I think that 'protected' members might be intended precisely to disallow
> things like this, so I'm not convinced 'better' is the right term here.
> Certainly 'more' code-reuse, if we're talking about protected member
> functions; 'less' code-reuse (and more risk to class invariants) if we're
> talking about protected data members.
>
> In the end, and it's a philosophical point, "encourage the use of classes
> and inheritance" reads to me like "encourage the use of the letter a". It's
> useful/powerful (or even "core", if you prefer), but you will be
> sufficiently tooled for your development work irrespective of your level of
> use in your code.
>

--
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/2bb71c28-e2c2-45e4-ad54-5a108e013539%40isocpp.org.

------=_Part_200_110670975.1503532367403
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I don&#39;t like the universal syntax. I think it adds too=
 much complexity in finding where methods are defined. What happens when fo=
o.a() exists but foo::a() does not? This is bound to be very confusing.<br>=
<br>The extend-cast idea is very useful, but I think it needs some better s=
yntax. Here&#39;s my proposal (basically):<br><br><div style=3D"background-=
color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: =
solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"=
><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">template</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ty=
pename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Alloc</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify"> =3D std::default_=
allocator&lt;T&gt; &gt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">class</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> extended_vector<br>=C2=A0</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
public</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&lt;</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"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">Alloc</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">...</span><span sty=
le=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"colo=
r: #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;" clas=
s=3D"styled-by-prettify"> extra_member_function</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br></span><br><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><code class=3D"prettyprint"><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>std</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"color:=
 #080;" class=3D"styled-by-prettify">&lt;int&gt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> vector_a</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>auto &amp;&amp; vector_extended =3D extend_=
cast&lt;extended_vector&lt;int&gt; &gt;(vector_a);</span></code></span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></co=
de></div>By inheriting from a reference we gain some advantages, it ensures=
 that there is no conversion between underlying data types (since it&#39;s =
just a reference to the same data) but we get extra member functions and th=
e ability to use protected members of the base class.<br>Inheriting from an=
 extended type could also be done using value semantics, yet the underlying=
 type would be a reference. This could be particularly useful for overridin=
g some member functions without proxying the entire class.<br>Also, this co=
uld be useful for adding additional &quot;phantom&quot; or &quot;ghost&quot=
; member variables. The ability to define a member variable on the &quot;ex=
tended&quot; type would be useful. (They could be initialized in the constr=
uctor of the class) Of course, you wouldn&#39;t be able to take a reference=
 to a temporary which means that you&#39;d need the  &amp;&amp; syntax whic=
h could cause some issues when forwarding? I&#39;d say maybe just add an &q=
uot;auto(ghost)&quot; keyword for this type of variable.<br><br>On Tuesday,=
 August 1, 2017 at 8:03:31 AM UTC-4, p_ha...@wargaming.net wrote:<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">On Wednesday, July 26, =
2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:<blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr">Currently there is no easy way to extend cl=
ass interfaces and still remain compatible with instances of the older inte=
rface. In certain cases, this might not be all that difficult to do if we e=
nsure that the binary layout does not change across interfaces.<br><br></di=
v></blockquote><div>=C2=A0</div><div><br></div><div>I feel that the problem=
 being solved (not liking the &quot;free-function&quot; generic programming=
 style currently encouraged by the STL) is something like an opt-in version=
 of half of &quot;universal call syntax&quot; (<font face=3D"courier new, m=
onospace">a.b(...) =3D&gt; b(a, ...)</font>), and/or a specific use-case fo=
r <font face=3D"courier new, monospace">operator.</font>, where the wrapper=
 type would have no state but the wrapped type.</div><div><br></div><div>On=
 the other hand, the suggested solution (<font face=3D"courier new, monospa=
ce">extend_cast</font>) seems feasible now using type traits, simply by hav=
ing the cast template function static_assert that the target inherits from =
the input, is standard_layout, and is the same size. You could probably app=
ly the static reflection work to be absolutely sure that someone isn&#39;t =
casting down to a type that stows something in the base class&#39;s padding=
, or otherwise messes with alignment to fool the size check.</div><div><br>=
</div><div><br></div><div><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"=
><div dir=3D"ltr">This feature would allow us to extend interfaces in C++ s=
tyle, enabling better encapsulation and readability and encourage the use o=
f classes and inheritance (and as a result better code reuse through access=
 to &#39;protected&#39; members of the base, which we would not get through=
 free functions).=C2=A0<br></div></blockquote><div><br></div><div>I think t=
hat &#39;protected&#39; members might be intended precisely to disallow thi=
ngs like this, so I&#39;m not convinced &#39;better&#39; is the right term =
here. Certainly &#39;more&#39; code-reuse, if we&#39;re talking about prote=
cted member functions; &#39;less&#39; code-reuse (and more risk to class in=
variants) if we&#39;re talking about protected data members.</div></div><di=
v><br></div><div>In the end, and it&#39;s a philosophical point, &quot;enco=
urage the use of classes and inheritance&quot; reads to me like &quot;encou=
rage the use of the letter a&quot;. It&#39;s useful/powerful (or even &quot=
;core&quot;, if you prefer), but you will be sufficiently tooled for your d=
evelopment work irrespective of your level of use in your code.</div></div>=
</blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/2bb71c28-e2c2-45e4-ad54-5a108e013539%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2bb71c28-e2c2-45e4-ad54-5a108e013539=
%40isocpp.org</a>.<br />

------=_Part_200_110670975.1503532367403--

------=_Part_199_1686183263.1503532367402--

.


Author: tortoise741@gmail.com
Date: Fri, 25 Aug 2017 18:07:41 -0700 (PDT)
Raw View
------=_Part_3364_2049565299.1503709661081
Content-Type: multipart/alternative;
 boundary="----=_Part_3365_324325071.1503709661082"

------=_Part_3365_324325071.1503709661082
Content-Type: text/plain; charset="UTF-8"



On Thursday, 24 August 2017 00:52:47 UTC+1, Ryan Nicholl wrote:
>
> I don't like the universal syntax. I think it adds too much complexity in
> finding where methods are defined. What happens when foo.a() exists but
> foo::a() does not? This is bound to be very confusing.
>
> The extend-cast idea is very useful, but I think it needs some better
> syntax. Here's my proposal (basically):
>
> template <typename T, typename Alloc = std::default_allocator<T> >
> class extended_vector
>  : public &std::vector<T, Alloc>
> {
>   ...
> public:
>   void extra_member_function() { ... }
> };
>
>
>
> std::vector<int> vector_a;
> auto && vector_extended = extend_cast<extended_vector<int> >(vector_a);
> By inheriting from a reference we gain some advantages, it ensures that
> there is no conversion between underlying data types (since it's just a
> reference to the same data) but we get extra member functions and the
> ability to use protected members of the base class.
> Inheriting from an extended type could also be done using value semantics,
> yet the underlying type would be a reference. This could be particularly
> useful for overriding some member functions without proxying the entire
> class.
> Also, this could be useful for adding additional "phantom" or "ghost"
> member variables. The ability to define a member variable on the "extended"
> type would be useful. (They could be initialized in the constructor of the
> class) Of course, you wouldn't be able to take a reference to a temporary
> which means that you'd need the && syntax which could cause some issues
> when forwarding? I'd say maybe just add an "auto(ghost)" keyword for this
> type of variable.
>
> On Tuesday, August 1, 2017 at 8:03:31 AM UTC-4, p_ha...@wargaming.net
> wrote:
>>
>> On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:
>>>
>>> Currently there is no easy way to extend class interfaces and still
>>> remain compatible with instances of the older interface. In certain cases,
>>> this might not be all that difficult to do if we ensure that the binary
>>> layout does not change across interfaces.
>>>
>>>
>>
>> I feel that the problem being solved (not liking the "free-function"
>> generic programming style currently encouraged by the STL) is something
>> like an opt-in version of half of "universal call syntax" (a.b(...) =>
>> b(a, ...)), and/or a specific use-case for operator., where the wrapper
>> type would have no state but the wrapped type.
>>
>> On the other hand, the suggested solution (extend_cast) seems feasible
>> now using type traits, simply by having the cast template function
>> static_assert that the target inherits from the input, is standard_layout,
>> and is the same size. You could probably apply the static reflection work
>> to be absolutely sure that someone isn't casting down to a type that stows
>> something in the base class's padding, or otherwise messes with alignment
>> to fool the size check.
>>
>>
>> This feature would allow us to extend interfaces in C++ style, enabling
>>> better encapsulation and readability and encourage the use of classes and
>>> inheritance (and as a result better code reuse through access to
>>> 'protected' members of the base, which we would not get through free
>>> functions).
>>>
>>
>> I think that 'protected' members might be intended precisely to disallow
>> things like this, so I'm not convinced 'better' is the right term here.
>> Certainly 'more' code-reuse, if we're talking about protected member
>> functions; 'less' code-reuse (and more risk to class invariants) if we're
>> talking about protected data members.
>>
>> In the end, and it's a philosophical point, "encourage the use of classes
>> and inheritance" reads to me like "encourage the use of the letter a". It's
>> useful/powerful (or even "core", if you prefer), but you will be
>> sufficiently tooled for your development work irrespective of your level of
>> use in your code.
>>
>
What is wrong with doing this by constructing the derived class from the
base and relying on the compiler to try and make it
as efficient as an extend_cast would be?

template <typename T, typename Alloc = std::default_allocator<T> >
class extended_vector
 : public &std::vector<T, Alloc>
{
  ...
public:
  extended_vector(vector& v):vector(v) { ... }

  void extra_member_function() { ... }
};


std::vector<int> vector_a;
extended_vector<int>(vector_a).extra_member_function(); //elide copy in
constructor here?

Actually that might work better with a move constructor

  extended_vector(vector&& v):vector(v) { ... }

I think that is the correct (but not efficient) way to code it now. Maybe
the 'extend_cast' part is actually
something needed to replace the copy or move constructor with a 'do nothing
/ placement new' constructor?

--
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/3868ac02-4a8f-401e-8e52-ec6642ec07d5%40isocpp.org.

------=_Part_3365_324325071.1503709661082
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Thursday, 24 August 2017 00:52:47 UTC+1, Ryan N=
icholl  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
>I don&#39;t like the universal syntax. I think it adds too much complexity=
 in finding where methods are defined. What happens when foo.a() exists but=
 foo::a() does not? This is bound to be very confusing.<br><br>The extend-c=
ast idea is very useful, but I think it needs some better syntax. Here&#39;=
s my proposal (basically):<br><br><div style=3D"background-color:rgb(250,25=
0,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><=
code><div><span style=3D"color:#008">template</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">&lt;</span><span style=3D"color:#008=
">typename</span><span style=3D"color:#000"> T</span><span style=3D"color:#=
660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">=
typename</span><span style=3D"color:#000"> </span><span style=3D"color:#606=
">Alloc</span><span style=3D"color:#660"> =3D std::default_allocator&lt;T&g=
t; &gt;</span><span style=3D"color:#000"><br></span><span style=3D"color:#0=
08">class</span><span style=3D"color:#000"> extended_vector<br>=C2=A0</span=
><span style=3D"color:#660">:</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#008">public</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">&amp;</span><span style=3D"color:#000">std</span><sp=
an style=3D"color:#660">::</span><span style=3D"color:#000">vector</span><s=
pan style=3D"color:#660">&lt;</span><span style=3D"color:#000">T</span><spa=
n style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#606">Alloc</span><span style=3D"color:#660">&gt;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span sty=
le=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">...</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#008">public</span=
><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 <=
/span><span style=3D"color:#008">void</span><span style=3D"color:#000"> ext=
ra_member_function</span><span style=3D"color:#660">()</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">...</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">}</span><span style=3D"color:#000">=
<br></span><span style=3D"color:#660">};</span><span style=3D"color:#000"><=
br><br></span><br><span style=3D"color:#000"><code><span style=3D"color:#00=
0"><br>std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
000">vector</span><span style=3D"color:#080">&lt;int&gt;</span><span style=
=3D"color:#000"> vector_a</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"><br>auto &amp;&amp; vector_extended =3D extend_cast&lt;e=
xtended_vector&lt;<wbr>int&gt; &gt;(vector_a);</span></code></span><span st=
yle=3D"color:#000"><br></span></div></code></div>By inheriting from a refer=
ence we gain some advantages, it ensures that there is no conversion betwee=
n underlying data types (since it&#39;s just a reference to the same data) =
but we get extra member functions and the ability to use protected members =
of the base class.<br>Inheriting from an extended type could also be done u=
sing value semantics, yet the underlying type would be a reference. This co=
uld be particularly useful for overriding some member functions without pro=
xying the entire class.<br>Also, this could be useful for adding additional=
 &quot;phantom&quot; or &quot;ghost&quot; member variables. The ability to =
define a member variable on the &quot;extended&quot; type would be useful. =
(They could be initialized in the constructor of the class) Of course, you =
wouldn&#39;t be able to take a reference to a temporary which means that yo=
u&#39;d need the  &amp;&amp; syntax which could cause some issues when forw=
arding? I&#39;d say maybe just add an &quot;auto(ghost)&quot; keyword for t=
his type of variable.<br><br>On Tuesday, August 1, 2017 at 8:03:31 AM UTC-4=
, <a>p_ha...@wargaming.net</a> wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsi=
n Mazumdar 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">C=
urrently there is no easy way to extend class interfaces and still remain c=
ompatible with instances of the older interface. In certain cases, this mig=
ht not be all that difficult to do if we ensure that the binary layout does=
 not change across interfaces.<br><br></div></blockquote><div>=C2=A0</div><=
div><br></div><div>I feel that the problem being solved (not liking the &qu=
ot;free-function&quot; generic programming style currently encouraged by th=
e STL) is something like an opt-in version of half of &quot;universal call =
syntax&quot; (<font face=3D"courier new, monospace">a.b(...) =3D&gt; b(a, .=
...)</font>), and/or a specific use-case for <font face=3D"courier new, mono=
space">operator.</font>, where the wrapper type would have no state but the=
 wrapped type.</div><div><br></div><div>On the other hand, the suggested so=
lution (<font face=3D"courier new, monospace">extend_cast</font>) seems fea=
sible now using type traits, simply by having the cast template function st=
atic_assert that the target inherits from the input, is standard_layout, an=
d is the same size. You could probably apply the static reflection work to =
be absolutely sure that someone isn&#39;t casting down to a type that stows=
 something in the base class&#39;s padding, or otherwise messes with alignm=
ent to fool the size check.</div><div><br></div><div><br></div><div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1p=
x solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">This feature wo=
uld allow us to extend interfaces in C++ style, enabling better encapsulati=
on and readability and encourage the use of classes and inheritance (and as=
 a result better code reuse through access to &#39;protected&#39; members o=
f the base, which we would not get through free functions).=C2=A0<br></div>=
</blockquote><div><br></div><div>I think that &#39;protected&#39; members m=
ight be intended precisely to disallow things like this, so I&#39;m not con=
vinced &#39;better&#39; is the right term here. Certainly &#39;more&#39; co=
de-reuse, if we&#39;re talking about protected member functions; &#39;less&=
#39; code-reuse (and more risk to class invariants) if we&#39;re talking ab=
out protected data members.</div></div><div><br></div><div>In the end, and =
it&#39;s a philosophical point, &quot;encourage the use of classes and inhe=
ritance&quot; reads to me like &quot;encourage the use of the letter a&quot=
;. It&#39;s useful/powerful (or even &quot;core&quot;, if you prefer), but =
you will be sufficiently tooled for your development work irrespective of y=
our level of use in your code.</div></div></blockquote></div></blockquote><=
div><br></div><div>What is wrong with doing this by constructing the derive=
d class from the base and relying on the compiler to try and make it=C2=A0<=
/div><div>as efficient as an extend_cast would be?</div><div><br></div><div=
><span style=3D"font-family: monospace; background-color: rgb(250, 250, 250=
); color: rgb(0, 0, 136);">template</span><span style=3D"font-family: monos=
pace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">=C2=A0</s=
pan><span style=3D"font-family: monospace; background-color: rgb(250, 250, =
250); color: rgb(102, 102, 0);">&lt;</span><span style=3D"font-family: mono=
space; background-color: rgb(250, 250, 250); color: rgb(0, 0, 136);">typena=
me</span><span style=3D"font-family: monospace; background-color: rgb(250, =
250, 250); color: rgb(0, 0, 0);">=C2=A0T</span><span style=3D"font-family: =
monospace; background-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">=
,</span><span style=3D"font-family: monospace; background-color: rgb(250, 2=
50, 250); color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"font-family: mo=
nospace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 136);">type=
name</span><span style=3D"font-family: monospace; background-color: rgb(250=
, 250, 250); color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"font-family:=
 monospace; background-color: rgb(250, 250, 250); color: rgb(102, 0, 102);"=
>Alloc</span><span style=3D"font-family: monospace; background-color: rgb(2=
50, 250, 250); color: rgb(102, 102, 0);">=C2=A0=3D std::default_allocator&l=
t;T&gt; &gt;</span><span style=3D"font-family: monospace; background-color:=
 rgb(250, 250, 250); color: rgb(0, 0, 0);"><br></span><span style=3D"font-f=
amily: monospace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 13=
6);">class</span><span style=3D"font-family: monospace; background-color: r=
gb(250, 250, 250); color: rgb(0, 0, 0);">=C2=A0extended_vector<br>=C2=A0</s=
pan><span style=3D"font-family: monospace; background-color: rgb(250, 250, =
250); color: rgb(102, 102, 0);">:</span><span style=3D"font-family: monospa=
ce; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">=C2=A0</spa=
n><span style=3D"font-family: monospace; background-color: rgb(250, 250, 25=
0); color: rgb(0, 0, 136);">public</span><span style=3D"font-family: monosp=
ace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">=C2=A0</sp=
an><span style=3D"font-family: monospace; background-color: rgb(250, 250, 2=
50); color: rgb(102, 102, 0);">&amp;</span><span style=3D"font-family: mono=
space; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">std</spa=
n><span style=3D"font-family: monospace; background-color: rgb(250, 250, 25=
0); color: rgb(102, 102, 0);">::</span><span style=3D"font-family: monospac=
e; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">vector</span=
><span style=3D"font-family: monospace; background-color: rgb(250, 250, 250=
); color: rgb(102, 102, 0);">&lt;</span><span style=3D"font-family: monospa=
ce; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">T</span><sp=
an style=3D"font-family: monospace; background-color: rgb(250, 250, 250); c=
olor: rgb(102, 102, 0);">,</span><span style=3D"font-family: monospace; bac=
kground-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">=C2=A0</span><span=
 style=3D"font-family: monospace; background-color: rgb(250, 250, 250); col=
or: rgb(102, 0, 102);">Alloc</span><span style=3D"font-family: monospace; b=
ackground-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">&gt;</span><=
span style=3D"font-family: monospace; background-color: rgb(250, 250, 250);=
 color: rgb(0, 0, 0);"><br></span><span style=3D"font-family: monospace; ba=
ckground-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">{</span><span=
 style=3D"font-family: monospace; background-color: rgb(250, 250, 250); col=
or: rgb(0, 0, 0);"><br>=C2=A0=C2=A0</span><span style=3D"font-family: monos=
pace; background-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">...</=
span><span style=3D"font-family: monospace; background-color: rgb(250, 250,=
 250); color: rgb(0, 0, 0);"><br></span><span style=3D"font-family: monospa=
ce; background-color: rgb(250, 250, 250); color: rgb(0, 0, 136);">public</s=
pan><span style=3D"font-family: monospace; background-color: rgb(250, 250, =
250); color: rgb(102, 102, 0);">:</span><span style=3D"font-family: monospa=
ce; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);"><br>=C2=A0 =
extended_vector(vector&amp; v):vector(v) { ... }</span></div><div><span sty=
le=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: =
rgb(0, 0, 0);"><br></span></div><div><span style=3D"font-family: monospace;=
 background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">=C2=A0=C2=A0</=
span><span style=3D"font-family: monospace; background-color: rgb(250, 250,=
 250); color: rgb(0, 0, 136);">void</span><span style=3D"font-family: monos=
pace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">=C2=A0ext=
ra_member_function</span><span style=3D"font-family: monospace; background-=
color: rgb(250, 250, 250); color: rgb(102, 102, 0);">()</span><span style=
=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: rg=
b(0, 0, 0);">=C2=A0</span><span style=3D"font-family: monospace; background=
-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">{</span><span style=
=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: rg=
b(0, 0, 0);">=C2=A0</span><span style=3D"font-family: monospace; background=
-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">...</span><span style=
=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: rg=
b(0, 0, 0);">=C2=A0</span><span style=3D"font-family: monospace; background=
-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">}</span><span style=
=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: rg=
b(0, 0, 0);"><br></span><span style=3D"font-family: monospace; background-c=
olor: rgb(250, 250, 250); color: rgb(102, 102, 0);">};</span><span style=3D=
"font-family: monospace; background-color: rgb(250, 250, 250); color: rgb(0=
, 0, 0);"><br><br></span><br style=3D"font-family: monospace; background-co=
lor: rgb(250, 250, 250);"><span style=3D"font-family: monospace; background=
-color: rgb(250, 250, 250); color: rgb(0, 0, 0);"><code>std<span style=3D"c=
olor: rgb(102, 102, 0);">::</span>vector<span style=3D"color: rgb(0, 136, 0=
);">&lt;int&gt;</span>=C2=A0vector_a<span style=3D"color: rgb(102, 102, 0);=
">;</span><br>extended_vector&lt;<wbr>int&gt;(vector_a).extra_member_functi=
on(); //elide copy in constructor here?</code></span><br></div><div><span s=
tyle=3D"font-family: monospace; background-color: rgb(250, 250, 250); color=
: rgb(0, 0, 0);"><code><br></code></span></div><div><div><span style=3D"fon=
t-family: monospace; background-color: rgb(250, 250, 250); color: rgb(0, 0,=
 0);">Actually that might work better with a move constructor</span></div><=
div><span style=3D"font-family: monospace; background-color: rgb(250, 250, =
250); color: rgb(0, 0, 0);"><br></span></div><div><span style=3D"font-famil=
y: monospace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">=
=C2=A0 extended_vector(vector&amp;&amp; v):vector(v) { ... }</span></div></=
div><div><span style=3D"font-family: monospace; background-color: rgb(250, =
250, 250); color: rgb(0, 0, 0);"><br></span></div><div><span style=3D"font-=
family: monospace; background-color: rgb(250, 250, 250); color: rgb(0, 0, 0=
);">I think that is the correct=C2=A0</span><span style=3D"background-color=
: rgb(250, 250, 250); color: rgb(0, 0, 0); font-family: monospace;">(but no=
t efficient)=C2=A0</span><span style=3D"background-color: rgb(250, 250, 250=
); color: rgb(0, 0, 0); font-family: monospace;">way to code it now. Maybe =
the &#39;extend_cast&#39; part is actually=C2=A0</span></div><div><span sty=
le=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: =
rgb(0, 0, 0);">something needed to replace the copy or move constructor wit=
h a &#39;do nothing / placement new&#39; constructor?</span></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/3868ac02-4a8f-401e-8e52-ec6642ec07d5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3868ac02-4a8f-401e-8e52-ec6642ec07d5=
%40isocpp.org</a>.<br />

------=_Part_3365_324325071.1503709661082--

------=_Part_3364_2049565299.1503709661081--

.


Author: tortoise741@gmail.com
Date: Sat, 26 Aug 2017 01:08:54 -0700 (PDT)
Raw View
------=_Part_3771_1815913091.1503734934148
Content-Type: multipart/alternative;
 boundary="----=_Part_3772_495442529.1503734934149"

------=_Part_3772_495442529.1503734934149
Content-Type: text/plain; charset="UTF-8"



On Saturday, 26 August 2017 02:07:41 UTC+1, Bruce Adams wrote:
>
>
>
> On Thursday, 24 August 2017 00:52:47 UTC+1, Ryan Nicholl wrote:
>>
>> I don't like the universal syntax. I think it adds too much complexity in
>> finding where methods are defined. What happens when foo.a() exists but
>> foo::a() does not? This is bound to be very confusing.
>>
>> The extend-cast idea is very useful, but I think it needs some better
>> syntax. Here's my proposal (basically):
>>
>> template <typename T, typename Alloc = std::default_allocator<T> >
>> class extended_vector
>>  : public &std::vector<T, Alloc>
>> {
>>   ...
>> public:
>>   void extra_member_function() { ... }
>> };
>>
>>
>>
>> std::vector<int> vector_a;
>> auto && vector_extended = extend_cast<extended_vector<int> >(vector_a);
>> By inheriting from a reference we gain some advantages, it ensures that
>> there is no conversion between underlying data types (since it's just a
>> reference to the same data) but we get extra member functions and the
>> ability to use protected members of the base class.
>> Inheriting from an extended type could also be done using value
>> semantics, yet the underlying type would be a reference. This could be
>> particularly useful for overriding some member functions without proxying
>> the entire class.
>> Also, this could be useful for adding additional "phantom" or "ghost"
>> member variables. The ability to define a member variable on the "extended"
>> type would be useful. (They could be initialized in the constructor of the
>> class) Of course, you wouldn't be able to take a reference to a temporary
>> which means that you'd need the && syntax which could cause some issues
>> when forwarding? I'd say maybe just add an "auto(ghost)" keyword for this
>> type of variable.
>>
>> On Tuesday, August 1, 2017 at 8:03:31 AM UTC-4, p_ha...@wargaming.net
>> wrote:
>>>
>>> On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:
>>>>
>>>> Currently there is no easy way to extend class interfaces and still
>>>> remain compatible with instances of the older interface. In certain cases,
>>>> this might not be all that difficult to do if we ensure that the binary
>>>> layout does not change across interfaces.
>>>>
>>>>
>>>
>>> I feel that the problem being solved (not liking the "free-function"
>>> generic programming style currently encouraged by the STL) is something
>>> like an opt-in version of half of "universal call syntax" (a.b(...) =>
>>> b(a, ...)), and/or a specific use-case for operator., where the wrapper
>>> type would have no state but the wrapped type.
>>>
>>> On the other hand, the suggested solution (extend_cast) seems feasible
>>> now using type traits, simply by having the cast template function
>>> static_assert that the target inherits from the input, is standard_layout,
>>> and is the same size. You could probably apply the static reflection work
>>> to be absolutely sure that someone isn't casting down to a type that stows
>>> something in the base class's padding, or otherwise messes with alignment
>>> to fool the size check.
>>>
>>>
>>> This feature would allow us to extend interfaces in C++ style, enabling
>>>> better encapsulation and readability and encourage the use of classes and
>>>> inheritance (and as a result better code reuse through access to
>>>> 'protected' members of the base, which we would not get through free
>>>> functions).
>>>>
>>>
>>> I think that 'protected' members might be intended precisely to disallow
>>> things like this, so I'm not convinced 'better' is the right term here.
>>> Certainly 'more' code-reuse, if we're talking about protected member
>>> functions; 'less' code-reuse (and more risk to class invariants) if we're
>>> talking about protected data members.
>>>
>>> In the end, and it's a philosophical point, "encourage the use of
>>> classes and inheritance" reads to me like "encourage the use of the letter
>>> a". It's useful/powerful (or even "core", if you prefer), but you will be
>>> sufficiently tooled for your development work irrespective of your level of
>>> use in your code.
>>>
>>
> What is wrong with doing this by constructing the derived class from the
> base and relying on the compiler to try and make it
> as efficient as an extend_cast would be?
>
> template <typename T, typename Alloc = std::default_allocator<T> >
> class extended_vector
>  : public &std::vector<T, Alloc>
> {
>   ...
> public:
>   extended_vector(vector& v):vector(v) { ... }
>
>   void extra_member_function() { ... }
> };
>
>
> std::vector<int> vector_a;
> extended_vector<int>(vector_a).extra_member_function(); //elide copy in
> constructor here?
>
> Actually that might work better with a move constructor
>
>   extended_vector(vector&& v):vector(v) { ... }
>
> I think that is the correct (but not efficient) way to code it now. Maybe
> the 'extend_cast' part is actually
> something needed to replace the copy or move constructor with a 'do
> nothing / placement new' constructor?
>

Of course the extended_vector is a different object from vector_a. So you
also have to 'copy' or 'move' it back and get that elided if you need to
switch back at any point.

The alternative is using perfect forwarding for all methods. That is
something that would be useful for all kinds of wrapper types.
I think that can be done with pure library functionality once reflection is
available. At the moment its a royal pain.

--
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/1c6a57a2-3a58-454d-817e-bd9fc91e6c99%40isocpp.org.

------=_Part_3772_495442529.1503734934149
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Saturday, 26 August 2017 02:07:41 UTC+1, Bruce =
Adams  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<br><br>On Thursday, 24 August 2017 00:52:47 UTC+1, Ryan Nicholl  wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">I don&#39;t like the =
universal syntax. I think it adds too much complexity in finding where meth=
ods are defined. What happens when foo.a() exists but foo::a() does not? Th=
is is bound to be very confusing.<br><br>The extend-cast idea is very usefu=
l, but I think it needs some better syntax. Here&#39;s my proposal (basical=
ly):<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rg=
b(187,187,187);border-style:solid;border-width:1px"><code><div><span style=
=3D"color:#008">template</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">&lt;</span><span style=3D"color:#008">typename</span><spa=
n style=3D"color:#000"> T</span><span style=3D"color:#660">,</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">typename</span><span =
style=3D"color:#000"> </span><span style=3D"color:#606">Alloc</span><span s=
tyle=3D"color:#660"> =3D std::default_allocator&lt;T&gt; &gt;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">class</span><span=
 style=3D"color:#000"> extended_vector<br>=C2=A0</span><span style=3D"color=
:#660">:</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">public</span><span style=3D"color:#000"> </span><span style=3D"color:#660=
">&amp;</span><span style=3D"color:#000">std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">vector</span><span style=3D"color:#6=
60">&lt;</span><span style=3D"color:#000">T</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">All=
oc</span><span style=3D"color:#660">&gt;</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:#660">...</span><span style=3D"color:#0=
00"><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 style=3D"color:#000"> extra_member_function</s=
pan><span style=3D"color:#660">()</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">...</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span styl=
e=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><br><sp=
an style=3D"color:#000"><code><span style=3D"color:#000"><br>std</span><spa=
n style=3D"color:#660">::</span><span style=3D"color:#000">vector</span><sp=
an style=3D"color:#080">&lt;int&gt;</span><span style=3D"color:#000"> vecto=
r_a</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br=
>auto &amp;&amp; vector_extended =3D extend_cast&lt;extended_vector&lt;<wbr=
>int&gt; &gt;(vector_a);</span></code></span><span style=3D"color:#000"><br=
></span></div></code></div>By inheriting from a reference we gain some adva=
ntages, it ensures that there is no conversion between underlying data type=
s (since it&#39;s just a reference to the same data) but we get extra membe=
r functions and the ability to use protected members of the base class.<br>=
Inheriting from an extended type could also be done using value semantics, =
yet the underlying type would be a reference. This could be particularly us=
eful for overriding some member functions without proxying the entire class=
..<br>Also, this could be useful for adding additional &quot;phantom&quot; o=
r &quot;ghost&quot; member variables. The ability to define a member variab=
le on the &quot;extended&quot; type would be useful. (They could be initial=
ized in the constructor of the class) Of course, you wouldn&#39;t be able t=
o take a reference to a temporary which means that you&#39;d need the  &amp=
;&amp; syntax which could cause some issues when forwarding? I&#39;d say ma=
ybe just add an &quot;auto(ghost)&quot; keyword for this type of variable.<=
br><br>On Tuesday, August 1, 2017 at 8:03:31 AM UTC-4, <a>p_ha...@wargaming=
..net</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On =
Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Currently there is no e=
asy way to extend class interfaces and still remain compatible with instanc=
es of the older interface. In certain cases, this might not be all that dif=
ficult to do if we ensure that the binary layout does not change across int=
erfaces.<br><br></div></blockquote><div>=C2=A0</div><div><br></div><div>I f=
eel that the problem being solved (not liking the &quot;free-function&quot;=
 generic programming style currently encouraged by the STL) is something li=
ke an opt-in version of half of &quot;universal call syntax&quot; (<font fa=
ce=3D"courier new, monospace">a.b(...) =3D&gt; b(a, ...)</font>), and/or a =
specific use-case for <font face=3D"courier new, monospace">operator.</font=
>, where the wrapper type would have no state but the wrapped type.</div><d=
iv><br></div><div>On the other hand, the suggested solution (<font face=3D"=
courier new, monospace">extend_cast</font>) seems feasible now using type t=
raits, simply by having the cast template function static_assert that the t=
arget inherits from the input, is standard_layout, and is the same size. Yo=
u could probably apply the static reflection work to be absolutely sure tha=
t someone isn&#39;t casting down to a type that stows something in the base=
 class&#39;s padding, or otherwise messes with alignment to fool the size c=
heck.</div><div><br></div><div><br></div><div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,20=
4);padding-left:1ex"><div dir=3D"ltr">This feature would allow us to extend=
 interfaces in C++ style, enabling better encapsulation and readability and=
 encourage the use of classes and inheritance (and as a result better code =
reuse through access to &#39;protected&#39; members of the base, which we w=
ould not get through free functions).=C2=A0<br></div></blockquote><div><br>=
</div><div>I think that &#39;protected&#39; members might be intended preci=
sely to disallow things like this, so I&#39;m not convinced &#39;better&#39=
; is the right term here. Certainly &#39;more&#39; code-reuse, if we&#39;re=
 talking about protected member functions; &#39;less&#39; code-reuse (and m=
ore risk to class invariants) if we&#39;re talking about protected data mem=
bers.</div></div><div><br></div><div>In the end, and it&#39;s a philosophic=
al point, &quot;encourage the use of classes and inheritance&quot; reads to=
 me like &quot;encourage the use of the letter a&quot;. It&#39;s useful/pow=
erful (or even &quot;core&quot;, if you prefer), but you will be sufficient=
ly tooled for your development work irrespective of your level of use in yo=
ur code.</div></div></blockquote></div></blockquote><div><br></div><div>Wha=
t is wrong with doing this by constructing the derived class from the base =
and relying on the compiler to try and make it=C2=A0</div><div>as efficient=
 as an extend_cast would be?</div><div><br></div><div><span style=3D"font-f=
amily:monospace;background-color:rgb(250,250,250);color:rgb(0,0,136)">templ=
ate</span><span style=3D"font-family:monospace;background-color:rgb(250,250=
,250);color:rgb(0,0,0)">=C2=A0</span><span style=3D"font-family:monospace;b=
ackground-color:rgb(250,250,250);color:rgb(102,102,0)">&lt;</span><span sty=
le=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0=
,136)">typename</span><span style=3D"font-family:monospace;background-color=
:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0T</span><span style=3D"font-famil=
y:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">,</span=
><span style=3D"font-family:monospace;background-color:rgb(250,250,250);col=
or:rgb(0,0,0)">=C2=A0</span><span style=3D"font-family:monospace;background=
-color:rgb(250,250,250);color:rgb(0,0,136)">typename</span><span style=3D"f=
ont-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><w=
br>=C2=A0</span><span style=3D"font-family:monospace;background-color:rgb(2=
50,250,250);color:rgb(102,0,102)">Alloc</span><span style=3D"font-family:mo=
nospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">=C2=A0=3D s=
td::default_allocator&lt;T&gt; &gt;</span><span style=3D"font-family:monosp=
ace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span><span st=
yle=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,=
0,136)">class</span><span style=3D"font-family:monospace;background-color:r=
gb(250,250,250);color:rgb(0,0,0)">=C2=A0extended_vector<br>=C2=A0</span><sp=
an style=3D"font-family:monospace;background-color:rgb(250,250,250);color:r=
gb(102,102,0)">:</span><span style=3D"font-family:monospace;background-colo=
r:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span><span style=3D"font-famil=
y:monospace;background-color:rgb(250,250,250);color:rgb(0,0,136)">public</s=
pan><span style=3D"font-family:monospace;background-color:rgb(250,250,250);=
color:rgb(0,0,0)">=C2=A0</span><span style=3D"font-family:monospace;backgro=
und-color:rgb(250,250,250);color:rgb(102,102,0)">&amp;</span><span style=3D=
"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=
std</span><span style=3D"font-family:monospace;background-color:rgb(250,250=
,250);color:rgb(102,102,0)">::</span><span style=3D"font-family:monospace;b=
ackground-color:rgb(250,250,250);color:rgb(0,0,0)">vector</span><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,1=
02,0)">&lt;</span><span style=3D"font-family:monospace;background-color:rgb=
(250,250,250);color:rgb(0,0,0)">T</span><span style=3D"font-family:monospac=
e;background-color:rgb(250,250,250);color:rgb(102,102,0)">,</span><span sty=
le=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0=
,0)">=C2=A0</span><span style=3D"font-family:monospace;background-color:rgb=
(250,250,250);color:rgb(102,0,102)">Allo<wbr>c</span><span style=3D"font-fa=
mily:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">&gt;=
</span><span style=3D"font-family:monospace;background-color:rgb(250,250,25=
0);color:rgb(0,0,0)"><br></span><span style=3D"font-family:monospace;backgr=
ound-color:rgb(250,250,250);color:rgb(102,102,0)">{</span><span style=3D"fo=
nt-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br=
>=C2=A0=C2=A0</span><span style=3D"font-family:monospace;background-color:r=
gb(250,250,250);color:rgb(102,102,0)">...</span><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span><s=
pan style=3D"font-family:monospace;background-color:rgb(250,250,250);color:=
rgb(0,0,136)">public</span><span style=3D"font-family:monospace;background-=
color:rgb(250,250,250);color:rgb(102,102,0)">:</span><span style=3D"font-fa=
mily:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br>=C2=
=A0 extended_vector(vector&amp; v):vector(v) { ... }</span></div><div><span=
 style=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb=
(0,0,0)"><br></span></div><div><span style=3D"font-family:monospace;backgro=
und-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0=C2=A0</span><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,1=
36)">void</span><span style=3D"font-family:monospace;background-color:rgb(2=
50,250,250);color:rgb(0,0,0)">=C2=A0extra_member_function</span><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,1=
02,0)">()</span><span style=3D"font-family:monospace;background-color:rgb(2=
50,250,250);color:rgb(0,0,0)"><wbr>=C2=A0</span><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">{</span><=
span style=3D"font-family:monospace;background-color:rgb(250,250,250);color=
:rgb(0,0,0)">=C2=A0</span><span style=3D"font-family:monospace;background-c=
olor:rgb(250,250,250);color:rgb(102,102,0)">...</span><span style=3D"font-f=
amily:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0<=
/span><span style=3D"font-family:monospace;background-color:rgb(250,250,250=
);color:rgb(102,102,0)">}</span><span style=3D"font-family:monospace;backgr=
ound-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span><span style=3D"fon=
t-family:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">=
};</span><span style=3D"font-family:monospace;background-color:rgb(250,250,=
250);color:rgb(0,0,0)"><br><br></span><br style=3D"font-family:monospace;ba=
ckground-color:rgb(250,250,250)"><span style=3D"font-family:monospace;backg=
round-color:rgb(250,250,250);color:rgb(0,0,0)"><code>std<span style=3D"colo=
r:rgb(102,102,0)">::</span>vector<span style=3D"color:rgb(0,136,0)">&lt;int=
&gt;</span>=C2=A0vector_a<span style=3D"color:rgb(102,102,0)">;</span><br>e=
xtended_vector&lt;int&gt;(vector_a)<wbr>.extra_member_function(); //elide c=
opy in constructor here?</code></span><br></div><div><span style=3D"font-fa=
mily:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><code><b=
r></code></span></div><div><div><span style=3D"font-family:monospace;backgr=
ound-color:rgb(250,250,250);color:rgb(0,0,0)">Actually that might work bett=
er with a move constructor</span></div><div><span style=3D"font-family:mono=
space;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span></div>=
<div><span style=3D"font-family:monospace;background-color:rgb(250,250,250)=
;color:rgb(0,0,0)">=C2=A0 extended_vector(vector&amp;&amp; v):vector(v) { .=
... }</span></div></div><div><span style=3D"font-family:monospace;background=
-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span></div><div><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0=
)">I think that is the correct=C2=A0</span><span style=3D"background-color:=
rgb(250,250,250);color:rgb(0,0,0);font-family:monospace">(but not efficient=
)=C2=A0</span><span style=3D"background-color:rgb(250,250,250);color:rgb(0,=
0,0);font-family:monospace">way to code it now. Maybe the &#39;extend_cast&=
#39; part is actually=C2=A0</span></div><div><span style=3D"font-family:mon=
ospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">something needed=
 to replace the copy or move constructor with a &#39;do nothing / placement=
 new&#39; constructor?</span></div></div></blockquote><div>=C2=A0</div><div=
>Of course the extended_vector is a different object from  vector_a. So you=
 also have to &#39;copy&#39; or &#39;move&#39; it back and get that elided =
if you need to</div><div>switch back at any point.<br></div><div><br></div>=
<div>The alternative is using perfect forwarding for all methods. That is s=
omething that would be useful for all kinds of wrapper types.</div><div>I t=
hink that can be done with pure library functionality once reflection is av=
ailable. At the moment its a royal pain.<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1c6a57a2-3a58-454d-817e-bd9fc91e6c99%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1c6a57a2-3a58-454d-817e-bd9fc91e6c99=
%40isocpp.org</a>.<br />

------=_Part_3772_495442529.1503734934149--

------=_Part_3771_1815913091.1503734934148--

.


Author: Ryan Nicholl <r.p.nicholl@gmail.com>
Date: Thu, 14 Dec 2017 12:40:58 -0800 (PST)
Raw View
------=_Part_3737_11807023.1513284058531
Content-Type: multipart/alternative;
 boundary="----=_Part_3738_1615031557.1513284058533"

------=_Part_3738_1615031557.1513284058533
Content-Type: text/plain; charset="UTF-8"

Well, allowing inheritance from a reference would give the following
advantages:

First, we can get the same advantages of extend cast, because the compiler
could see that they have the same address, and thus the compiler doesn't
need to create a separate variable.

Extend cast has a couple of issues. First, if the compiler ONLY checks the
binary layout, then you could convert a vector to an extended string by
accident.

If the compiler instead checks that the base class is the same, we
basically have a cast that allows us to cast vector A to B, only the memory
of A is destroyed?
Or is it? What actually happens to the vector object? Is it now a vector?
or is it something else? What is the type of that object now?
What happens if you do:
l1:
vector<foo> a = ...;
l2:
extended_vector<foo> & b = extend_cast<extended_vector<foo>&> (a);
b.bar();
goto l1;

So what happens after the goto statement? Do we call the destructor of b
and not the destructor of a? What happens if we do "goto l2;" instead? How
do we "unextend" the class?

Reinterpreting the data of the class as though it were another type is done
with reinterpret_cast, I'm not sure what the extend cast is supposed to
other than make that more defined behavior. But IIRC, reinterpret cast has
defined behavior for certain POD types.

What it seems to me that you want is a type safe version of reinterpret
cast. But that raises some issues, we can't check "binary compatibility",
only whether or not either the POD layout is the same, or the types share
some base in some way.

Lets say we only check the binary layout, so you could cast a std::string
to a extended_vector<char> because both look something like:
struct { size_t; size_t; char *; };
But they are not compatible. (trailing 0s, SSO could be different, etc.) So
instead of casting based on binary layout, lets say you cast based upon the
base class.
Now what do we do when we try to "extend_cast" something that wasn't meant
to be extended? Like for example having your iterator inherit from your
const_iterator. Thus, you could extend_cast a const_iterator to an
iterator. Doesn't sound legit to me. That's why I suggest a different
syntax. I'm going to improve on it a bit here.

class foo { ... };

class bar : public &foo
{
 public:
  bar(...) {  }
};

Now the only rule is that bar must initialize the reference to foo. This
provides a transparent forwarding of the public methods of foo to a user of
the bar class, and also provides any additional methods of bar.
It's also possible that ~bar could "convert back" a temporary change.

While this is mostly possible using proxy objects, you have to manually
forward every member function. Inheriting from a reference solves the
problem in a neater way.
It would also have other uses, consider these theoretical example wrappers
around a C string:
class local_c_string
: public &c_string
{
  mutable size_t len;
  mutable bool len_cached;
public:
 local_c_string(c_string & i) : c_string(i), len(0), len_cached(0) {}
 bool size() const
 {
   if( len_cached) return len;
   len = strlen();
   return len;
 }
 local_c_string & operator = (c_string & other)
 {
   static_cast<c_string&>(*this) = other;
   len_cached = false;
 }

};

The compiler would be able to detect when the references are equal and thus
optimize out the declaration, and it doesn't get into any of the wackyness
of extend cast.

To avoid the pitfall of thinking that the derived class actually inherits
from the reference class, maybe the syntax should be different?

typename &local_c_string localstr(str);

This would help distinguish between objects that are references and objects
that contain references. The typename is required because I think the
grammar might be ambiguous in templates otherwise.
But I'm not sure if that's an optimal solution, since it would cause
reference objects to be treated differently from objects that contain
references. To make sure it evaluates correctly using templates, we could
say that the full type of a reference object is "&foo" rather than the
class name "foo". So then:
class bar
 : public &baz
{
....
};

template<typename T>
class foo
{
....
public:
  using value_type = T;
};

foo <typename& bar> a;
// Here, a::value_type would be "&bar" rather than "bar" (not to be
confused with bar&)

bar b;
// This line would cause a compilation error. bar is not a typename.
&bar b;
// Also an error because it's not clear whether & is the unary operator &
or a typename
typename & bar b (a);
// Not an error, typename& used.


This prevents them from being accidentally used where a normal object is
expected, but retains the ability to use them in templates without
requiring special syntax.
If there is a case where you want the default operator = etc. to function
like it would for an object containing a reference rather than an reference
object , you could apply the static/inline keyword:

class foo
 : static &bar
{
....
};
// Functions like an object containing a reference and the type name is
"foo"

class baz
 : inline &bar
{
....
};
// Functions like a reference instead of an object. Type name is "&baz"

I'm not sure whether the default should be static or inline though. Maybe
always require it explicitly?


On Friday, August 25, 2017 at 9:07:41 PM UTC-4, Bruce Adams wrote:
>
>
>
> On Thursday, 24 August 2017 00:52:47 UTC+1, Ryan Nicholl wrote:
>>
>> I don't like the universal syntax. I think it adds too much complexity in
>> finding where methods are defined. What happens when foo.a() exists but
>> foo::a() does not? This is bound to be very confusing.
>>
>> The extend-cast idea is very useful, but I think it needs some better
>> syntax. Here's my proposal (basically):
>>
>> template <typename T, typename Alloc = std::default_allocator<T> >
>> class extended_vector
>>  : public &std::vector<T, Alloc>
>> {
>>   ...
>> public:
>>   void extra_member_function() { ... }
>> };
>>
>>
>>
>> std::vector<int> vector_a;
>> auto && vector_extended = extend_cast<extended_vector<int> >(vector_a);
>> By inheriting from a reference we gain some advantages, it ensures that
>> there is no conversion between underlying data types (since it's just a
>> reference to the same data) but we get extra member functions and the
>> ability to use protected members of the base class.
>> Inheriting from an extended type could also be done using value
>> semantics, yet the underlying type would be a reference. This could be
>> particularly useful for overriding some member functions without proxying
>> the entire class.
>> Also, this could be useful for adding additional "phantom" or "ghost"
>> member variables. The ability to define a member variable on the "extended"
>> type would be useful. (They could be initialized in the constructor of the
>> class) Of course, you wouldn't be able to take a reference to a temporary
>> which means that you'd need the && syntax which could cause some issues
>> when forwarding? I'd say maybe just add an "auto(ghost)" keyword for this
>> type of variable.
>>
>> On Tuesday, August 1, 2017 at 8:03:31 AM UTC-4, p_ha...@wargaming.net
>> wrote:
>>>
>>> On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:
>>>>
>>>> Currently there is no easy way to extend class interfaces and still
>>>> remain compatible with instances of the older interface. In certain cases,
>>>> this might not be all that difficult to do if we ensure that the binary
>>>> layout does not change across interfaces.
>>>>
>>>>
>>>
>>> I feel that the problem being solved (not liking the "free-function"
>>> generic programming style currently encouraged by the STL) is something
>>> like an opt-in version of half of "universal call syntax" (a.b(...) =>
>>> b(a, ...)), and/or a specific use-case for operator., where the wrapper
>>> type would have no state but the wrapped type.
>>>
>>> On the other hand, the suggested solution (extend_cast) seems feasible
>>> now using type traits, simply by having the cast template function
>>> static_assert that the target inherits from the input, is standard_layout,
>>> and is the same size. You could probably apply the static reflection work
>>> to be absolutely sure that someone isn't casting down to a type that stows
>>> something in the base class's padding, or otherwise messes with alignment
>>> to fool the size check.
>>>
>>>
>>> This feature would allow us to extend interfaces in C++ style, enabling
>>>> better encapsulation and readability and encourage the use of classes and
>>>> inheritance (and as a result better code reuse through access to
>>>> 'protected' members of the base, which we would not get through free
>>>> functions).
>>>>
>>>
>>> I think that 'protected' members might be intended precisely to disallow
>>> things like this, so I'm not convinced 'better' is the right term here.
>>> Certainly 'more' code-reuse, if we're talking about protected member
>>> functions; 'less' code-reuse (and more risk to class invariants) if we're
>>> talking about protected data members.
>>>
>>> In the end, and it's a philosophical point, "encourage the use of
>>> classes and inheritance" reads to me like "encourage the use of the letter
>>> a". It's useful/powerful (or even "core", if you prefer), but you will be
>>> sufficiently tooled for your development work irrespective of your level of
>>> use in your code.
>>>
>>
> What is wrong with doing this by constructing the derived class from the
> base and relying on the compiler to try and make it
> as efficient as an extend_cast would be?
>
> template <typename T, typename Alloc = std::default_allocator<T> >
> class extended_vector
>  : public &std::vector<T, Alloc>
> {
>   ...
> public:
>   extended_vector(vector& v):vector(v) { ... }
>
>   void extra_member_function() { ... }
> };
>
>
> std::vector<int> vector_a;
> extended_vector<int>(vector_a).extra_member_function(); //elide copy in
> constructor here?
>
> Actually that might work better with a move constructor
>
>   extended_vector(vector&& v):vector(v) { ... }
>
> I think that is the correct (but not efficient) way to code it now. Maybe
> the 'extend_cast' part is actually
> something needed to replace the copy or move constructor with a 'do
> nothing / placement new' constructor?
>

--
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/469d032f-8db1-4743-815d-ee57a5540c2d%40isocpp.org.

------=_Part_3738_1615031557.1513284058533
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Well, allowing inheritance from a reference would give the=
 following advantages:<br><br>First, we can get the same advantages of exte=
nd cast, because the compiler could see that they have the same address, an=
d thus the compiler doesn&#39;t need to create a separate variable.<div><br=
></div><div>Extend cast has a couple of issues. First, if the compiler ONLY=
 checks the binary layout, then you could convert a vector to an extended s=
tring by accident.</div><div><br></div><div>If the compiler instead checks =
that the base class is the same, we basically have a cast that allows us to=
 cast vector A to B, only the memory of A is destroyed?</div><div>Or is it?=
 What actually happens to the vector object? Is it now a vector? or is it s=
omething else? What is the type of that object now?</div><div>What happens =
if you do:</div><div><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: #000;" class=3D"styled-by-p=
rettify">l1</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>vect=
or</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&lt;foo&=
gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> a </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">...;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>l2</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>extended_vector</span><span style=3D"color:=
 #080;" class=3D"styled-by-prettify">&lt;foo&gt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&amp;</span><font color=3D"#000000"><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> b </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> extend_cast</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify">extended_vector</span><span style=3D"color: #=
080;" class=3D"styled-by-prettify">&lt;foo&gt;</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&amp;&gt;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">a</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>b</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">bar</span><spa=
n 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">goto</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> l1</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">;</span></font></div></code></div><br>So what h=
appens after the goto statement? Do we call the destructor of b and not the=
 destructor of a? What happens if we do &quot;goto l2;&quot; instead? How d=
o we &quot;unextend&quot; the class?</div><div><br></div><div>Reinterpretin=
g the data of the class as though it were another type is done with reinter=
pret_cast, I&#39;m not sure what the extend cast is supposed to other than =
make that more defined behavior. But IIRC, reinterpret cast has defined beh=
avior for certain POD types.</div><div><br></div><div>What it seems to me t=
hat you want is a type safe version of reinterpret cast. But that raises so=
me issues, we can&#39;t check &quot;binary compatibility&quot;, only whethe=
r or not either the POD layout is the same, or the types share some base in=
 some way.</div><div><br></div><div>Lets say we only check the binary layou=
t, so you could cast a std::string to a extended_vector&lt;char&gt; because=
 both look something like:</div><div><div class=3D"prettyprint" style=3D"ba=
ckground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); borde=
r-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> size_t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> size_t</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">char</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">*;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">};</span></div></code></div>But they are not compatible. (tr=
ailing 0s, SSO could be different, etc.) So instead of casting based on bin=
ary layout, lets say you cast based upon the base class.</div><div>Now what=
 do we do when we try to &quot;extend_cast&quot; something that wasn&#39;t =
meant to be extended? Like for example having your iterator inherit from yo=
ur const_iterator. Thus, you could extend_cast a const_iterator to an itera=
tor. Doesn&#39;t sound legit to me. That&#39;s why I suggest a different sy=
ntax. I&#39;m going to improve on it a bit here.</div><div><br></div><div><=
div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); bo=
rder-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; wor=
d-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettypri=
nt"><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> foo </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-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-pr=
ettify">class</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> bar </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: #008;" class=3D"styled-by-prettify">public</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify">foo<br></span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0</span><span style=3D"color: #008;" clas=
s=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-b=
y-prettify"><br>=C2=A0 bar</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(...)</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">}</span><font color=3D"#0=
00000"><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span></=
font></div></code></div><br>Now the only rule is that bar must initialize t=
he reference to foo. This provides a transparent forwarding of the public m=
ethods of foo to a user of the bar class, and also provides any additional =
methods of bar.</div><div>It&#39;s also possible that ~bar could &quot;conv=
ert back&quot; a temporary change.=C2=A0</div><div><br></div><div>While thi=
s is mostly possible using proxy objects, you have to manually forward ever=
y member function. Inheriting from a reference solves the problem in a neat=
er way.</div><div>It would also have other uses, consider these theoretical=
 example wrappers around a C string:</div><div><div class=3D"prettyprint" s=
tyle=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 1=
87); 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">class</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> local_c_string<br></span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">public</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">c_string<br></span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{</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">mut=
able</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> size_=
t len</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 </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">mutable</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> len_cached</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;" c=
lass=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0local_c_string</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><font color=3D"#000000"><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">c_string </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> i</span></font><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> c_string</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">i</span><span style=3D"color: #660;" class=3D"styled-by-prettify">),</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> len</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">),</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> len_cached</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">(</span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </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">bool</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> size</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><font color=3D"#666600"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">=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: #008;" class=3D"styled-by-prettify">if</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> len_cached</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"style=
d-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> len</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0len </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 strlen</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">ret=
urn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> len</s=
pan><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></span></font><span style=
=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0local_c_string </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">=3D</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: #000;" class=3D"styled-by-pr=
ettify">c_string </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> other</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><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">static_cast</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">c_string</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&gt;(*</span><f=
ont color=3D"#000000"><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">this</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> other</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=A0len_cached </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">false</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span></font><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span></div></code></div><br>The compiler would be abl=
e to detect when the references are equal and thus optimize out the declara=
tion, and it doesn&#39;t get into any of the wackyness of extend cast.</div=
><div><br></div><div>To avoid the pitfall of thinking that the derived clas=
s actually inherits from the reference class, maybe the syntax should be di=
fferent?</div><div><br></div><div><div class=3D"prettyprint" style=3D"backg=
round-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-s=
tyle: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pret=
typrint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">local_c_string localstr</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">str</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">);</span><font color=3D"#666600"></font></div></code></div><br>This=
 would help distinguish between objects that are references and objects tha=
t contain references. The typename is required because I think the grammar =
might be ambiguous in templates otherwise.</div><div>But I&#39;m not sure i=
f that&#39;s an optimal solution, since it would cause reference objects to=
 be treated differently from objects that contain references. To make sure =
it evaluates correctly using templates, we could say that the full type of =
a reference object is &quot;&amp;foo&quot; rather than the class name &quot=
;foo&quot;. So then:</div><div><div class=3D"prettyprint" style=3D"backgrou=
nd-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-styl=
e: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyp=
rint"><div class=3D"subprettyprint"><font color=3D"#660066"><span style=3D"=
color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> bar<br>=C2=A0</span><span style=3D"c=
olor: #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">public</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">baz<br></span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">...</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">template</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> foo<br></span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">public</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">using</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> value_type </span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">=3D</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"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br><br>foo </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">typ=
ename</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> bar</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> a</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: #800=
;" class=3D"styled-by-prettify">// </span></font><span style=3D"background-=
color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;"><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">Here, a::value_type w=
ould be &quot;&amp;bar&quot; rather than &quot;bar&quot; (not to be confuse=
d with bar&amp;)</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br><br>bar b</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: #800;" class=3D"styled-by-prettify">// Thi=
s line would cause a compilation error. bar is not a typename.</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">bar b</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// Also an error because it&#39;s not clear whether=
 &amp; is the unary operator &amp; or a typename</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> bar b </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #800;" class=3D"styled-by-prettify">// Not an error, ty=
pename&amp; used.</span></span></div></code></div><br><br></div><div>This p=
revents them from being accidentally used where a normal object is expected=
, but retains the ability to use them in templates without requiring specia=
l syntax.</div><div>If there is a case where you want the default operator =
=3D etc. to function like it would for an object containing a reference rat=
her than an reference object , you could apply the static/inline keyword:</=
div><div><br></div><div><div class=3D"prettyprint" style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><font color=3D"#660066"><span style=3D"color: =
#008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> foo<br>=C2=A0</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">static</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">b=
ar<br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">...</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #800;" =
class=3D"styled-by-prettify">// Functions like an object containing a refer=
ence and the type name is &quot;foo&quot;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br><br></span></font><span style=3D"color: =
#008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> baz<br>=C2=A0</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><font color=3D"#000088"><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">inline</span></font><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify">bar<br></span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">// Functions li=
ke a reference instead of an object. Type name is &quot;&amp;baz&quot;</spa=
n><font color=3D"#660066"><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></font></div></code></div><br>I&#39;m not sure whether =
the default should be static or inline though. Maybe always require it expl=
icitly?<br></div><div><br></div><div><br></div><div>On Friday, August 25, 2=
017 at 9:07:41 PM UTC-4, Bruce Adams 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"><br><br>On Thursday, 24 August 2017 00:52:47 =
UTC+1, Ryan Nicholl  wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr">I don&#39;t like the universal syntax. I think it adds too much co=
mplexity in finding where methods are defined. What happens when foo.a() ex=
ists but foo::a() does not? This is bound to be very confusing.<br><br>The =
extend-cast idea is very useful, but I think it needs some better syntax. H=
ere&#39;s my proposal (basically):<br><br><div style=3D"background-color:rg=
b(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-widt=
h:1px"><code><div><span style=3D"color:#008">template</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">&lt;</span><span style=3D"co=
lor:#008">typename</span><span style=3D"color:#000"> T</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#606">Alloc</span><span style=3D"color:#660"> =3D std::default_allocato=
r&lt;T&gt; &gt;</span><span style=3D"color:#000"><br></span><span style=3D"=
color:#008">class</span><span style=3D"color:#000"> extended_vector<br>=C2=
=A0</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">public</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000">std<=
/span><span style=3D"color:#660">::</span><span style=3D"color:#000">vector=
</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">T</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Alloc</span><span style=3D"color:#660">&gt;</spa=
n><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:#660">...=
</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">pub=
lic</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br=
>=C2=A0 </span><span style=3D"color:#008">void</span><span style=3D"color:#=
000"> extra_member_function</span><span style=3D"color:#660">()</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span styl=
e=3D"color:#000"> </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"><br></span><span style=3D"color:#660">};</span><span style=3D"co=
lor:#000"><br><br></span><br><span style=3D"color:#000"><code><span style=
=3D"color:#000"><br>std</span><span style=3D"color:#660">::</span><span sty=
le=3D"color:#000">vector</span><span style=3D"color:#080">&lt;int&gt;</span=
><span style=3D"color:#000"> vector_a</span><span style=3D"color:#660">;</s=
pan><span style=3D"color:#000"><br>auto &amp;&amp; vector_extended =3D exte=
nd_cast&lt;extended_vector&lt;<wbr>int&gt; &gt;(vector_a);</span></code></s=
pan><span style=3D"color:#000"><br></span></div></code></div>By inheriting =
from a reference we gain some advantages, it ensures that there is no conve=
rsion between underlying data types (since it&#39;s just a reference to the=
 same data) but we get extra member functions and the ability to use protec=
ted members of the base class.<br>Inheriting from an extended type could al=
so be done using value semantics, yet the underlying type would be a refere=
nce. This could be particularly useful for overriding some member functions=
 without proxying the entire class.<br>Also, this could be useful for addin=
g additional &quot;phantom&quot; or &quot;ghost&quot; member variables. The=
 ability to define a member variable on the &quot;extended&quot; type would=
 be useful. (They could be initialized in the constructor of the class) Of =
course, you wouldn&#39;t be able to take a reference to a temporary which m=
eans that you&#39;d need the  &amp;&amp; syntax which could cause some issu=
es when forwarding? I&#39;d say maybe just add an &quot;auto(ghost)&quot; k=
eyword for this type of variable.<br><br>On Tuesday, August 1, 2017 at 8:03=
:31 AM UTC-4, <a>p_ha...@wargaming.net</a> wrote:<blockquote class=3D"gmail=
_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr">On Wednesday, July 26, 2017 at 10:47:38 AM U=
TC+10, Tahsin Mazumdar wrote:<blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr">Currently there is no easy way to extend class interfaces and st=
ill remain compatible with instances of the older interface. In certain cas=
es, this might not be all that difficult to do if we ensure that the binary=
 layout does not change across interfaces.<br><br></div></blockquote><div>=
=C2=A0</div><div><br></div><div>I feel that the problem being solved (not l=
iking the &quot;free-function&quot; generic programming style currently enc=
ouraged by the STL) is something like an opt-in version of half of &quot;un=
iversal call syntax&quot; (<font face=3D"courier new, monospace">a.b(...) =
=3D&gt; b(a, ...)</font>), and/or a specific use-case for <font face=3D"cou=
rier new, monospace">operator.</font>, where the wrapper type would have no=
 state but the wrapped type.</div><div><br></div><div>On the other hand, th=
e suggested solution (<font face=3D"courier new, monospace">extend_cast</fo=
nt>) seems feasible now using type traits, simply by having the cast templa=
te function static_assert that the target inherits from the input, is stand=
ard_layout, and is the same size. You could probably apply the static refle=
ction work to be absolutely sure that someone isn&#39;t casting down to a t=
ype that stows something in the base class&#39;s padding, or otherwise mess=
es with alignment to fool the size check.</div><div><br></div><div><br></di=
v><div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">T=
his feature would allow us to extend interfaces in C++ style, enabling bett=
er encapsulation and readability and encourage the use of classes and inher=
itance (and as a result better code reuse through access to &#39;protected&=
#39; members of the base, which we would not get through free functions).=
=C2=A0<br></div></blockquote><div><br></div><div>I think that &#39;protecte=
d&#39; members might be intended precisely to disallow things like this, so=
 I&#39;m not convinced &#39;better&#39; is the right term here. Certainly &=
#39;more&#39; code-reuse, if we&#39;re talking about protected member funct=
ions; &#39;less&#39; code-reuse (and more risk to class invariants) if we&#=
39;re talking about protected data members.</div></div><div><br></div><div>=
In the end, and it&#39;s a philosophical point, &quot;encourage the use of =
classes and inheritance&quot; reads to me like &quot;encourage the use of t=
he letter a&quot;. It&#39;s useful/powerful (or even &quot;core&quot;, if y=
ou prefer), but you will be sufficiently tooled for your development work i=
rrespective of your level of use in your code.</div></div></blockquote></di=
v></blockquote><div><br></div><div>What is wrong with doing this by constru=
cting the derived class from the base and relying on the compiler to try an=
d make it=C2=A0</div><div>as efficient as an extend_cast would be?</div><di=
v><br></div><div><span style=3D"font-family:monospace;background-color:rgb(=
250,250,250);color:rgb(0,0,136)">template</span><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span>=
<span style=3D"font-family:monospace;background-color:rgb(250,250,250);colo=
r:rgb(102,102,0)">&lt;</span><span style=3D"font-family:monospace;backgroun=
d-color:rgb(250,250,250);color:rgb(0,0,136)">typename</span><span style=3D"=
font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=
=C2=A0T</span><span style=3D"font-family:monospace;background-color:rgb(250=
,250,250);color:rgb(102,102,0)">,</span><span style=3D"font-family:monospac=
e;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span><span st=
yle=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,=
0,136)">typename</span><span style=3D"font-family:monospace;background-colo=
r:rgb(250,250,250);color:rgb(0,0,0)"><wbr>=C2=A0</span><span style=3D"font-=
family:monospace;background-color:rgb(250,250,250);color:rgb(102,0,102)">Al=
loc</span><span style=3D"font-family:monospace;background-color:rgb(250,250=
,250);color:rgb(102,102,0)">=C2=A0=3D std::default_allocator&lt;T&gt; &gt;<=
/span><span style=3D"font-family:monospace;background-color:rgb(250,250,250=
);color:rgb(0,0,0)"><br></span><span style=3D"font-family:monospace;backgro=
und-color:rgb(250,250,250);color:rgb(0,0,136)">class</span><span style=3D"f=
ont-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=
=C2=A0extended_vector<br>=C2=A0</span><span style=3D"font-family:monospace;=
background-color:rgb(250,250,250);color:rgb(102,102,0)">:</span><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0=
)">=C2=A0</span><span style=3D"font-family:monospace;background-color:rgb(2=
50,250,250);color:rgb(0,0,136)">public</span><span style=3D"font-family:mon=
ospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span><sp=
an style=3D"font-family:monospace;background-color:rgb(250,250,250);color:r=
gb(102,102,0)">&amp;</span><span style=3D"font-family:monospace;background-=
color:rgb(250,250,250);color:rgb(0,0,0)">std</span><span style=3D"font-fami=
ly:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">::</sp=
an><span style=3D"font-family:monospace;background-color:rgb(250,250,250);c=
olor:rgb(0,0,0)">vector</span><span style=3D"font-family:monospace;backgrou=
nd-color:rgb(250,250,250);color:rgb(102,102,0)">&lt;</span><span style=3D"f=
ont-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">T<=
/span><span style=3D"font-family:monospace;background-color:rgb(250,250,250=
);color:rgb(102,102,0)">,</span><span style=3D"font-family:monospace;backgr=
ound-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span><span style=3D"f=
ont-family:monospace;background-color:rgb(250,250,250);color:rgb(102,0,102)=
">Allo<wbr>c</span><span style=3D"font-family:monospace;background-color:rg=
b(250,250,250);color:rgb(102,102,0)">&gt;</span><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span><s=
pan style=3D"font-family:monospace;background-color:rgb(250,250,250);color:=
rgb(102,102,0)">{</span><span style=3D"font-family:monospace;background-col=
or:rgb(250,250,250);color:rgb(0,0,0)"><br>=C2=A0=C2=A0</span><span style=3D=
"font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,102,=
0)">...</span><span style=3D"font-family:monospace;background-color:rgb(250=
,250,250);color:rgb(0,0,0)"><br></span><span style=3D"font-family:monospace=
;background-color:rgb(250,250,250);color:rgb(0,0,136)">public</span><span s=
tyle=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(1=
02,102,0)">:</span><span style=3D"font-family:monospace;background-color:rg=
b(250,250,250);color:rgb(0,0,0)"><br>=C2=A0 extended_vector(vector&amp; v):=
vector(v) { ... }</span></div><div><span style=3D"font-family:monospace;bac=
kground-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span></div><div><spa=
n style=3D"font-family:monospace;background-color:rgb(250,250,250);color:rg=
b(0,0,0)">=C2=A0=C2=A0</span><span style=3D"font-family:monospace;backgroun=
d-color:rgb(250,250,250);color:rgb(0,0,136)">void</span><span style=3D"font=
-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=
=A0extra_member_function</span><span style=3D"font-family:monospace;backgro=
und-color:rgb(250,250,250);color:rgb(102,102,0)">()</span><span style=3D"fo=
nt-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><wb=
r>=C2=A0</span><span style=3D"font-family:monospace;background-color:rgb(25=
0,250,250);color:rgb(102,102,0)">{</span><span style=3D"font-family:monospa=
ce;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span><span s=
tyle=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(1=
02,102,0)">...</span><span style=3D"font-family:monospace;background-color:=
rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">}</span><=
span style=3D"font-family:monospace;background-color:rgb(250,250,250);color=
:rgb(0,0,0)"><br></span><span style=3D"font-family:monospace;background-col=
or:rgb(250,250,250);color:rgb(102,102,0)">};</span><span style=3D"font-fami=
ly:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br><br></=
span><br style=3D"font-family:monospace;background-color:rgb(250,250,250)">=
<span style=3D"font-family:monospace;background-color:rgb(250,250,250);colo=
r:rgb(0,0,0)"><code>std<span style=3D"color:rgb(102,102,0)">::</span>vector=
<span style=3D"color:rgb(0,136,0)">&lt;int&gt;</span>=C2=A0vector_a<span st=
yle=3D"color:rgb(102,102,0)">;</span><br>extended_vector&lt;int&gt;(vector_=
a)<wbr>.extra_member_function(); //elide copy in constructor here?</code></=
span><br></div><div><span style=3D"font-family:monospace;background-color:r=
gb(250,250,250);color:rgb(0,0,0)"><code><br></code></span></div><div><div><=
span style=3D"font-family:monospace;background-color:rgb(250,250,250);color=
:rgb(0,0,0)">Actually that might work better with a move constructor</span>=
</div><div><span style=3D"font-family:monospace;background-color:rgb(250,25=
0,250);color:rgb(0,0,0)"><br></span></div><div><span style=3D"font-family:m=
onospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0 extende=
d_vector(vector&amp;&amp; v):vector(v) { ... }</span></div></div><div><span=
 style=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb=
(0,0,0)"><br></span></div><div><span style=3D"font-family:monospace;backgro=
und-color:rgb(250,250,250);color:rgb(0,0,0)">I think that is the correct=C2=
=A0</span><span style=3D"background-color:rgb(250,250,250);color:rgb(0,0,0)=
;font-family:monospace">(but not efficient)=C2=A0</span><span style=3D"back=
ground-color:rgb(250,250,250);color:rgb(0,0,0);font-family:monospace">way t=
o code it now. Maybe the &#39;extend_cast&#39; part is actually=C2=A0</span=
></div><div><span style=3D"font-family:monospace;background-color:rgb(250,2=
50,250);color:rgb(0,0,0)">something needed to replace the copy or move cons=
tructor with a &#39;do nothing / placement new&#39; constructor?</span></di=
v></div></blockquote></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/469d032f-8db1-4743-815d-ee57a5540c2d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/469d032f-8db1-4743-815d-ee57a5540c2d=
%40isocpp.org</a>.<br />

------=_Part_3738_1615031557.1513284058533--

------=_Part_3737_11807023.1513284058531--

.


Author: adrian.hawryluk@gmail.com
Date: Mon, 18 Dec 2017 06:35:30 -0800 (PST)
Raw View
------=_Part_172_261870679.1513607730660
Content-Type: multipart/alternative;
 boundary="----=_Part_173_1350394924.1513607730661"

------=_Part_173_1350394924.1513607730661
Content-Type: text/plain; charset="UTF-8"



On Saturday, August 26, 2017 at 4:08:54 AM UTC-4, Bruce Adams wrote:
>
>
>
> On Saturday, 26 August 2017 02:07:41 UTC+1, Bruce Adams wrote:
>>
>>
>>
>> On Thursday, 24 August 2017 00:52:47 UTC+1, Ryan Nicholl wrote:
>>>
>>> I don't like the universal syntax. I think it adds too much complexity
>>> in finding where methods are defined. What happens when foo.a() exists but
>>> foo::a() does not? This is bound to be very confusing.
>>>
>>> The extend-cast idea is very useful, but I think it needs some better
>>> syntax. Here's my proposal (basically):
>>>
>>> template <typename T, typename Alloc = std::default_allocator<T> >
>>> class extended_vector
>>>  : public &std::vector<T, Alloc>
>>> {
>>>   ...
>>> public:
>>>   void extra_member_function() { ... }
>>> };
>>>
>>>
>>>
>>> std::vector<int> vector_a;
>>> auto && vector_extended = extend_cast<extended_vector<int> >(vector_a);
>>> By inheriting from a reference we gain some advantages, it ensures that
>>> there is no conversion between underlying data types (since it's just a
>>> reference to the same data) but we get extra member functions and the
>>> ability to use protected members of the base class.
>>> Inheriting from an extended type could also be done using value
>>> semantics, yet the underlying type would be a reference. This could be
>>> particularly useful for overriding some member functions without proxying
>>> the entire class.
>>> Also, this could be useful for adding additional "phantom" or "ghost"
>>> member variables. The ability to define a member variable on the "extended"
>>> type would be useful. (They could be initialized in the constructor of the
>>> class) Of course, you wouldn't be able to take a reference to a temporary
>>> which means that you'd need the && syntax which could cause some issues
>>> when forwarding? I'd say maybe just add an "auto(ghost)" keyword for this
>>> type of variable.
>>>
>>> On Tuesday, August 1, 2017 at 8:03:31 AM UTC-4, p_ha...@wargaming.net
>>> wrote:
>>>>
>>>> On Wednesday, July 26, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar
>>>> wrote:
>>>>>
>>>>> Currently there is no easy way to extend class interfaces and still
>>>>> remain compatible with instances of the older interface. In certain cases,
>>>>> this might not be all that difficult to do if we ensure that the binary
>>>>> layout does not change across interfaces.
>>>>>
>>>>>
>>>>
>>>> I feel that the problem being solved (not liking the "free-function"
>>>> generic programming style currently encouraged by the STL) is something
>>>> like an opt-in version of half of "universal call syntax" (a.b(...) =>
>>>> b(a, ...)), and/or a specific use-case for operator., where the
>>>> wrapper type would have no state but the wrapped type.
>>>>
>>>> On the other hand, the suggested solution (extend_cast) seems feasible
>>>> now using type traits, simply by having the cast template function
>>>> static_assert that the target inherits from the input, is standard_layout,
>>>> and is the same size. You could probably apply the static reflection work
>>>> to be absolutely sure that someone isn't casting down to a type that stows
>>>> something in the base class's padding, or otherwise messes with alignment
>>>> to fool the size check.
>>>>
>>>>
>>>> This feature would allow us to extend interfaces in C++ style, enabling
>>>>> better encapsulation and readability and encourage the use of classes and
>>>>> inheritance (and as a result better code reuse through access to
>>>>> 'protected' members of the base, which we would not get through free
>>>>> functions).
>>>>>
>>>>
>>>> I think that 'protected' members might be intended precisely to
>>>> disallow things like this, so I'm not convinced 'better' is the right term
>>>> here. Certainly 'more' code-reuse, if we're talking about protected member
>>>> functions; 'less' code-reuse (and more risk to class invariants) if we're
>>>> talking about protected data members.
>>>>
>>>> In the end, and it's a philosophical point, "encourage the use of
>>>> classes and inheritance" reads to me like "encourage the use of the letter
>>>> a". It's useful/powerful (or even "core", if you prefer), but you will be
>>>> sufficiently tooled for your development work irrespective of your level of
>>>> use in your code.
>>>>
>>>
>> What is wrong with doing this by constructing the derived class from the
>> base and relying on the compiler to try and make it
>> as efficient as an extend_cast would be?
>>
>> template <typename T, typename Alloc = std::default_allocator<T> >
>> class extended_vector
>>  : public &std::vector<T, Alloc>
>> {
>>   ...
>> public:
>>   extended_vector(vector& v):vector(v) { ... }
>>
>>   void extra_member_function() { ... }
>> };
>>
>>
>> std::vector<int> vector_a;
>> extended_vector<int>(vector_a).extra_member_function(); //elide copy in
>> constructor here?
>>
>> Actually that might work better with a move constructor
>>
>>   extended_vector(vector&& v):vector(v) { ... }
>>
>> I think that is the correct (but not efficient) way to code it now.
>> Maybe the 'extend_cast' part is actually
>> something needed to replace the copy or move constructor with a 'do
>> nothing / placement new' constructor?
>>
>
> Of course the extended_vector is a different object from vector_a. So you
> also have to 'copy' or 'move' it back and get that elided if you need to
> switch back at any point.
>
> The alternative is using perfect forwarding for all methods. That is
> something that would be useful for all kinds of wrapper types.
> I think that can be done with pure library functionality once reflection
> is available. At the moment its a royal pain.
>

I have used a forward macro to generate the boilerplate to deal with this.
I think it was like:

#define FWD_FN(from, to)                  \
  template <typename...Ts>                \
  auto from(Ts...args) {                  \
    return to(std::forward<Ts>(args)...); \
  }


--
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/570d5aa1-90cc-47bd-b6bb-2908dc9624ab%40isocpp.org.

------=_Part_173_1350394924.1513607730661
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Saturday, August 26, 2017 at 4:08:54 AM UTC-4, =
Bruce Adams wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr"><br><br>On Saturday, 26 August 2017 02:07:41 UTC+1, Bruce Adams  wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>On Thursd=
ay, 24 August 2017 00:52:47 UTC+1, Ryan Nicholl  wrote:<blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr">I don&#39;t like the universal syntax.=
 I think it adds too much complexity in finding where methods are defined. =
What happens when foo.a() exists but foo::a() does not? This is bound to be=
 very confusing.<br><br>The extend-cast idea is very useful, but I think it=
 needs some better syntax. Here&#39;s my proposal (basically):<br><br><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">te=
mplate</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
&lt;</span><span style=3D"color:#008">typename</span><span style=3D"color:#=
000"> T</span><span style=3D"color:#660">,</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">typename</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#606">Alloc</span><span style=3D"color:#660=
"> =3D std::default_allocator&lt;T&gt; &gt;</span><span style=3D"color:#000=
"><br></span><span style=3D"color:#008">class</span><span style=3D"color:#0=
00"> extended_vector<br>=C2=A0</span><span style=3D"color:#660">:</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">public</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">&amp;</span><spa=
n style=3D"color:#000">std</span><span style=3D"color:#660">::</span><span =
style=3D"color:#000">vector</span><span style=3D"color:#660">&lt;</span><sp=
an style=3D"color:#000">T</span><span style=3D"color:#660">,</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#606">Alloc</span><span sty=
le=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><sp=
an style=3D"color:#660">...</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#008">public</span><span style=3D"color:#660">:</span><sp=
an style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">void</=
span><span style=3D"color:#000"> extra_member_function</span><span style=3D=
"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">...</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>}</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">}=
;</span><span style=3D"color:#000"><br><br></span><br><span style=3D"color:=
#000"><code><span style=3D"color:#000"><br>std</span><span style=3D"color:#=
660">::</span><span style=3D"color:#000">vector</span><span style=3D"color:=
#080">&lt;int&gt;</span><span style=3D"color:#000"> vector_a</span><span st=
yle=3D"color:#660">;</span><span style=3D"color:#000"><br>auto &amp;&amp; v=
ector_extended =3D extend_cast&lt;extended_vector&lt;<wbr>int&gt; &gt;(vect=
or_a);</span></code></span><span style=3D"color:#000"><br></span></div></co=
de></div>By inheriting from a reference we gain some advantages, it ensures=
 that there is no conversion between underlying data types (since it&#39;s =
just a reference to the same data) but we get extra member functions and th=
e ability to use protected members of the base class.<br>Inheriting from an=
 extended type could also be done using value semantics, yet the underlying=
 type would be a reference. This could be particularly useful for overridin=
g some member functions without proxying the entire class.<br>Also, this co=
uld be useful for adding additional &quot;phantom&quot; or &quot;ghost&quot=
; member variables. The ability to define a member variable on the &quot;ex=
tended&quot; type would be useful. (They could be initialized in the constr=
uctor of the class) Of course, you wouldn&#39;t be able to take a reference=
 to a temporary which means that you&#39;d need the  &amp;&amp; syntax whic=
h could cause some issues when forwarding? I&#39;d say maybe just add an &q=
uot;auto(ghost)&quot; keyword for this type of variable.<br><br>On Tuesday,=
 August 1, 2017 at 8:03:31 AM UTC-4, <a>p_ha...@wargaming.net</a> wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, July 26=
, 2017 at 10:47:38 AM UTC+10, Tahsin Mazumdar wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr">Currently there is no easy way to extend =
class interfaces and still remain compatible with instances of the older in=
terface. In certain cases, this might not be all that difficult to do if we=
 ensure that the binary layout does not change across interfaces.<br><br></=
div></blockquote><div>=C2=A0</div><div><br></div><div>I feel that the probl=
em being solved (not liking the &quot;free-function&quot; generic programmi=
ng style currently encouraged by the STL) is something like an opt-in versi=
on of half of &quot;universal call syntax&quot; (<font face=3D"courier new,=
 monospace">a.b(...) =3D&gt; b(a, ...)</font>), and/or a specific use-case =
for <font face=3D"courier new, monospace">operator.</font>, where the wrapp=
er type would have no state but the wrapped type.</div><div><br></div><div>=
On the other hand, the suggested solution (<font face=3D"courier new, monos=
pace">extend_cast</font>) seems feasible now using type traits, simply by h=
aving the cast template function static_assert that the target inherits fro=
m the input, is standard_layout, and is the same size. You could probably a=
pply the static reflection work to be absolutely sure that someone isn&#39;=
t casting down to a type that stows something in the base class&#39;s paddi=
ng, or otherwise messes with alignment to fool the size check.</div><div><b=
r></div><div><br></div><div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1e=
x"><div dir=3D"ltr">This feature would allow us to extend interfaces in C++=
 style, enabling better encapsulation and readability and encourage the use=
 of classes and inheritance (and as a result better code reuse through acce=
ss to &#39;protected&#39; members of the base, which we would not get throu=
gh free functions).=C2=A0<br></div></blockquote><div><br></div><div>I think=
 that &#39;protected&#39; members might be intended precisely to disallow t=
hings like this, so I&#39;m not convinced &#39;better&#39; is the right ter=
m here. Certainly &#39;more&#39; code-reuse, if we&#39;re talking about pro=
tected member functions; &#39;less&#39; code-reuse (and more risk to class =
invariants) if we&#39;re talking about protected data members.</div></div><=
div><br></div><div>In the end, and it&#39;s a philosophical point, &quot;en=
courage the use of classes and inheritance&quot; reads to me like &quot;enc=
ourage the use of the letter a&quot;. It&#39;s useful/powerful (or even &qu=
ot;core&quot;, if you prefer), but you will be sufficiently tooled for your=
 development work irrespective of your level of use in your code.</div></di=
v></blockquote></div></blockquote><div><br></div><div>What is wrong with do=
ing this by constructing the derived class from the base and relying on the=
 compiler to try and make it=C2=A0</div><div>as efficient as an extend_cast=
 would be?</div><div><br></div><div><span style=3D"font-family:monospace;ba=
ckground-color:rgb(250,250,250);color:rgb(0,0,136)">template</span><span st=
yle=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,=
0,0)">=C2=A0</span><span style=3D"font-family:monospace;background-color:rg=
b(250,250,250);color:rgb(102,102,0)">&lt;</span><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(0,0,136)">typename</s=
pan><span style=3D"font-family:monospace;background-color:rgb(250,250,250);=
color:rgb(0,0,0)">=C2=A0T</span><span style=3D"font-family:monospace;backgr=
ound-color:rgb(250,250,250);color:rgb(102,102,0)">,</span><span style=3D"fo=
nt-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=
=A0</span><span style=3D"font-family:monospace;background-color:rgb(250,250=
,250);color:rgb(0,0,136)">typename</span><span style=3D"font-family:monospa=
ce;background-color:rgb(250,250,250);color:rgb(0,0,0)"><wbr>=C2=A0</span><s=
pan style=3D"font-family:monospace;background-color:rgb(250,250,250);color:=
rgb(102,0,102)">Alloc</span><span style=3D"font-family:monospace;background=
-color:rgb(250,250,250);color:rgb(102,102,0)">=C2=A0=3D std::default_alloca=
tor&lt;T&gt; &gt;</span><span style=3D"font-family:monospace;background-col=
or:rgb(250,250,250);color:rgb(0,0,0)"><br></span><span style=3D"font-family=
:monospace;background-color:rgb(250,250,250);color:rgb(0,0,136)">class</spa=
n><span style=3D"font-family:monospace;background-color:rgb(250,250,250);co=
lor:rgb(0,0,0)">=C2=A0extended_vector<br>=C2=A0</span><span style=3D"font-f=
amily:monospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">:</=
span><span style=3D"font-family:monospace;background-color:rgb(250,250,250)=
;color:rgb(0,0,0)">=C2=A0</span><span style=3D"font-family:monospace;backgr=
ound-color:rgb(250,250,250);color:rgb(0,0,136)">public</span><span style=3D=
"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=
=C2=A0</span><span style=3D"font-family:monospace;background-color:rgb(250,=
250,250);color:rgb(102,102,0)">&amp;</span><span style=3D"font-family:monos=
pace;background-color:rgb(250,250,250);color:rgb(0,0,0)">std</span><span st=
yle=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(10=
2,102,0)">::</span><span style=3D"font-family:monospace;background-color:rg=
b(250,250,250);color:rgb(0,0,0)">vector</span><span style=3D"font-family:mo=
nospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">&lt;</span>=
<span style=3D"font-family:monospace;background-color:rgb(250,250,250);colo=
r:rgb(0,0,0)">T</span><span style=3D"font-family:monospace;background-color=
:rgb(250,250,250);color:rgb(102,102,0)">,</span><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span>=
<span style=3D"font-family:monospace;background-color:rgb(250,250,250);colo=
r:rgb(102,0,102)">Allo<wbr>c</span><span style=3D"font-family:monospace;bac=
kground-color:rgb(250,250,250);color:rgb(102,102,0)">&gt;</span><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0=
)"><br></span><span style=3D"font-family:monospace;background-color:rgb(250=
,250,250);color:rgb(102,102,0)">{</span><span style=3D"font-family:monospac=
e;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br>=C2=A0=C2=A0</spa=
n><span style=3D"font-family:monospace;background-color:rgb(250,250,250);co=
lor:rgb(102,102,0)">...</span><span style=3D"font-family:monospace;backgrou=
nd-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span><span style=3D"font-=
family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,136)">publ=
ic</span><span style=3D"font-family:monospace;background-color:rgb(250,250,=
250);color:rgb(102,102,0)">:</span><span style=3D"font-family:monospace;bac=
kground-color:rgb(250,250,250);color:rgb(0,0,0)"><br>=C2=A0 extended_vector=
(vector&amp; v):vector(v) { ... }</span></div><div><span style=3D"font-fami=
ly:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)"><br></span=
></div><div><span style=3D"font-family:monospace;background-color:rgb(250,2=
50,250);color:rgb(0,0,0)">=C2=A0=C2=A0</span><span style=3D"font-family:mon=
ospace;background-color:rgb(250,250,250);color:rgb(0,0,136)">void</span><sp=
an style=3D"font-family:monospace;background-color:rgb(250,250,250);color:r=
gb(0,0,0)">=C2=A0extra_member_function</span><span style=3D"font-family:mon=
ospace;background-color:rgb(250,250,250);color:rgb(102,102,0)">()</span><sp=
an style=3D"font-family:monospace;background-color:rgb(250,250,250);color:r=
gb(0,0,0)"><wbr>=C2=A0</span><span style=3D"font-family:monospace;backgroun=
d-color:rgb(250,250,250);color:rgb(102,102,0)">{</span><span style=3D"font-=
family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0=
</span><span style=3D"font-family:monospace;background-color:rgb(250,250,25=
0);color:rgb(102,102,0)">...</span><span style=3D"font-family:monospace;bac=
kground-color:rgb(250,250,250);color:rgb(0,0,0)">=C2=A0</span><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(102,1=
02,0)">}</span><span style=3D"font-family:monospace;background-color:rgb(25=
0,250,250);color:rgb(0,0,0)"><br></span><span style=3D"font-family:monospac=
e;background-color:rgb(250,250,250);color:rgb(102,102,0)">};</span><span st=
yle=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,=
0,0)"><br><br></span><br style=3D"font-family:monospace;background-color:rg=
b(250,250,250)"><span style=3D"font-family:monospace;background-color:rgb(2=
50,250,250);color:rgb(0,0,0)"><code>std<span style=3D"color:rgb(102,102,0)"=
>::</span>vector<span style=3D"color:rgb(0,136,0)">&lt;int&gt;</span>=C2=A0=
vector_a<span style=3D"color:rgb(102,102,0)">;</span><br>extended_vector&lt=
;int&gt;(vector_a)<wbr>.extra_member_function(); //elide copy in constructo=
r here?</code></span><br></div><div><span style=3D"font-family:monospace;ba=
ckground-color:rgb(250,250,250);color:rgb(0,0,0)"><code><br></code></span><=
/div><div><div><span style=3D"font-family:monospace;background-color:rgb(25=
0,250,250);color:rgb(0,0,0)">Actually that might work better with a move co=
nstructor</span></div><div><span style=3D"font-family:monospace;background-=
color:rgb(250,250,250);color:rgb(0,0,0)"><br></span></div><div><span style=
=3D"font-family:monospace;background-color:rgb(250,250,250);color:rgb(0,0,0=
)">=C2=A0 extended_vector(vector&amp;&amp; v):vector(v) { ... }</span></div=
></div><div><span style=3D"font-family:monospace;background-color:rgb(250,2=
50,250);color:rgb(0,0,0)"><br></span></div><div><span style=3D"font-family:=
monospace;background-color:rgb(250,250,250);color:rgb(0,0,0)">I think that =
is the correct=C2=A0</span><span style=3D"background-color:rgb(250,250,250)=
;color:rgb(0,0,0);font-family:monospace">(but not efficient)=C2=A0</span><s=
pan style=3D"background-color:rgb(250,250,250);color:rgb(0,0,0);font-family=
:monospace">way to code it now. Maybe the &#39;extend_cast&#39; part is act=
ually=C2=A0</span></div><div><span style=3D"font-family:monospace;backgroun=
d-color:rgb(250,250,250);color:rgb(0,0,0)">something needed to replace the =
copy or move constructor with a &#39;do nothing / placement new&#39; constr=
uctor?</span></div></div></blockquote><div>=C2=A0</div><div>Of course the e=
xtended_vector is a different object from  vector_a. So you also have to &#=
39;copy&#39; or &#39;move&#39; it back and get that elided if you need to</=
div><div>switch back at any point.<br></div><div><br></div><div>The alterna=
tive is using perfect forwarding for all methods. That is something that wo=
uld be useful for all kinds of wrapper types.</div><div>I think that can be=
 done with pure library functionality once reflection is available. At the =
moment its a royal pain.<br></div></div></blockquote><div><br></div><div>I =
have used a forward macro to generate the boilerplate to deal with this.=C2=
=A0 I think it was like:</div><div><br></div><div class=3D"prettyprint" sty=
le=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187=
); border-style: solid; border-width: 1px; word-wrap: break-word;"><code cl=
ass=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #80=
0;" class=3D"styled-by-prettify">#define</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> FWD_FN</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">from</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> to</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">\</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #0=
08;" 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">&lt;</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">typename</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">...</span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Ts</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">\</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">from</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Ts</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">args</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =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 </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">return</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> to</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">forward</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">args</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)...);</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">\</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></=
span></div></code></div><div><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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/570d5aa1-90cc-47bd-b6bb-2908dc9624ab%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/570d5aa1-90cc-47bd-b6bb-2908dc9624ab=
%40isocpp.org</a>.<br />

------=_Part_173_1350394924.1513607730661--

------=_Part_172_261870679.1513607730660--

.


Author: adrian.hawryluk@gmail.com
Date: Mon, 18 Dec 2017 07:18:28 -0800 (PST)
Raw View
------=_Part_195_392883858.1513610308169
Content-Type: multipart/alternative;
 boundary="----=_Part_196_549565035.1513610308171"

------=_Part_196_549565035.1513610308171
Content-Type: text/plain; charset="UTF-8"

On Thursday, December 14, 2017 at 3:40:58 PM UTC-5, Ryan Nicholl wrote:
>
> Well, allowing inheritance from a reference would give the following
> advantages:
>
> First, we can get the same advantages of extend cast, because the compiler
> could see that they have the same address, and thus the compiler doesn't
> need to create a separate variable.
>
> Extend cast has a couple of issues. First, if the compiler ONLY checks the
> binary layout, then you could convert a vector to an extended string by
> accident.
>
> If the compiler instead checks that the base class is the same, we
> basically have a cast that allows us to cast vector A to B, only the memory
> of A is destroyed?
> Or is it? What actually happens to the vector object? Is it now a vector?
> or is it something else? What is the type of that object now?
> What happens if you do:
> l1:
> vector<foo> a = ...;
> l2:
> extended_vector<foo> & b = extend_cast<extended_vector<foo>&> (a);
> b.bar();
> goto l1;
>
> So what happens after the goto statement? Do we call the destructor of b
> and not the destructor of a? What happens if we do "goto l2;" instead? How
> do we "unextend" the class?
>

References don't use destructors.  They don't have ownership.

Reinterpreting the data of the class as though it were another type is done
> with reinterpret_cast, I'm not sure what the extend cast is supposed to
> other than make that more defined behavior. But IIRC, reinterpret cast has
> defined behavior for certain POD types.
>
> What it seems to me that you want is a type safe version of reinterpret
> cast. But that raises some issues, we can't check "binary compatibility",
> only whether or not either the POD layout is the same, or the types share
> some base in some way.
>
> Lets say we only check the binary layout, so you could cast a std::string
> to a extended_vector<char> because both look something like:
> struct { size_t; size_t; char *; };
> But they are not compatible. (trailing 0s, SSO could be different, etc.)
> So instead of casting based on binary layout, lets say you cast based upon
> the base class.
> Now what do we do when we try to "extend_cast" something that wasn't meant
> to be extended? Like for example having your iterator inherit from your
> const_iterator. Thus, you could extend_cast a const_iterator to an
> iterator. Doesn't sound legit to me. That's why I suggest a different
> syntax. I'm going to improve on it a bit here.
>
> class foo { ... };
>
> class bar : public &foo
> {
>  public:
>   bar(...) {  }
> };
>
> Now the only rule is that bar must initialize the reference to foo. This
> provides a transparent forwarding of the public methods of foo to a user of
> the bar class, and also provides any additional methods of bar.
> It's also possible that ~bar could "convert back" a temporary change.
>
> While this is mostly possible using proxy objects, you have to manually
> forward every member function. Inheriting from a reference solves the
> problem in a neater way.
> It would also have other uses, consider these theoretical example wrappers
> around a C string:
> class local_c_string
> : public &c_string
> {
>   mutable size_t len;
>   mutable bool len_cached;
> public:
>  local_c_string(c_string & i) : c_string(i), len(0), len_cached(0) {}
>  bool size() const
>  {
>    if( len_cached) return len;
>    len = strlen();
>    return len;
>  }
>  local_c_string & operator = (c_string & other)
>  {
>    static_cast<c_string&>(*this) = other;
>    len_cached = false;
>  }
>
> };
>
> The compiler would be able to detect when the references are equal and
> thus optimize out the declaration, and it doesn't get into any of the
> wackyness of extend cast.
>
> To avoid the pitfall of thinking that the derived class actually inherits
> from the reference class, maybe the syntax should be different?
>
> typename &local_c_string localstr(str);
>
> This would help distinguish between objects that are references and
> objects that contain references. The typename is required because I think
> the grammar might be ambiguous in templates otherwise.
> But I'm not sure if that's an optimal solution, since it would cause
> reference objects to be treated differently from objects that contain
> references. To make sure it evaluates correctly using templates, we could
> say that the full type of a reference object is "&foo" rather than the
> class name "foo". So then:
> class bar
>  : public &baz
> {
> ...
> };
>
> template<typename T>
> class foo
> {
> ...
> public:
>   using value_type = T;
> };
>
> foo <typename& bar> a;
> // Here, a::value_type would be "&bar" rather than "bar" (not to be
> confused with bar&)
>
> bar b;
> // This line would cause a compilation error. bar is not a typename.
> &bar b;
> // Also an error because it's not clear whether & is the unary operator &
> or a typename
> typename & bar b (a);
> // Not an error, typename& used.
>
>
> This prevents them from being accidentally used where a normal object is
> expected, but retains the ability to use them in templates without
> requiring special syntax.
> If there is a case where you want the default operator = etc. to function
> like it would for an object containing a reference rather than an reference
> object , you could apply the static/inline keyword:
>
> class foo
>  : static &bar
> {
> ...
> };
> // Functions like an object containing a reference and the type name is
> "foo"
>
> class baz
>  : inline &bar
> {
> ...
> };
> // Functions like a reference instead of an object. Type name is "&baz"
>
> I'm not sure whether the default should be static or inline though. Maybe
> always require it explicitly?
>

I like the idea of inheriting from a reference type. This would allow
extending a type safely, and even allow adding member variables (though
without any members, it could be considered just as an retyped alias
object). As it is inheriting from a reference, it has no ownership of the
underlying referenced object, so it's destruction would leave the
underlying object intact.

I'm going to have to look at your examples again, because I think our
trains of thought diverged. I'm thinking that the new object that derived
from a reference object could be used just like a regular object. and
doesn't really need any special handling. However, the developer would have
to be aware of the decoupled lifespans.

Also, not sure why you put the & before the typename. Why not after, as it
seems more natural?
class X
{
  public:
    ~X() { std::cout << "~X()" << std::endl; }
};

class Y : public X&
{
  public:
    Y() = delete;      // This can never be made
    Y(X& x) : X&(x) {} // Required signature.  This would be default impl
though.
    ~Y() { std::cout << "~Y()" << std::endl; }
};

class Z : public X&&
{
  public:
    Z() = delete;        // This can never be made
    Z(X&& x) : X&&(x) {} // Required signature.  This would be default impl
though.
    ~Z() { std::cout << "~Z()" << std::endl; }
};

int main()
{
  X x;
  {
    Y y0{x};    // Y's destructor is called, but X's is not
    Y y1{X()};  // Invalid
  }

  {
    Z z0{x};    // Invalid
    Z z1{X()};  // Z's destructor is called, but X's is not
  }
  return 0; // X's destructor is called
}


Haven't completely thought through if there should be a difference between
an lvalue and rvalue reference inheritance though.  Unnecessary?







ss

--
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/758cd43b-2c3f-4f6e-91bb-4fbca9aad79c%40isocpp.org.

------=_Part_196_549565035.1513610308171
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, December 14, 2017 at 3:40:58 PM UTC-5, Ryan N=
icholl wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px=
 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div=
 dir=3D"ltr">Well, allowing inheritance from a reference would give the fol=
lowing advantages:<br><br>First, we can get the same advantages of extend c=
ast, because the compiler could see that they have the same address, and th=
us the compiler doesn&#39;t need to create a separate variable.<div><br></d=
iv><div>Extend cast has a couple of issues. First, if the compiler ONLY che=
cks the binary layout, then you could convert a vector to an extended strin=
g by accident.</div><div><br></div><div>If the compiler instead checks that=
 the base class is the same, we basically have a cast that allows us to cas=
t vector A to B, only the memory of A is destroyed?</div><div>Or is it? Wha=
t actually happens to the vector object? Is it now a vector? or is it somet=
hing else? What is the type of that object now?</div><div>What happens if y=
ou do:</div><div><div style=3D"border-width: 1px; border-style: solid; bord=
er-color: rgb(187, 187, 187); background-color: rgb(250, 250, 250); word-wr=
ap: break-word;"><code><span style=3D"color: rgb(0, 0, 0);">l1</span><span =
style=3D"color: rgb(102, 102, 0);">:</span><span style=3D"color: rgb(0, 0, =
0);"><br>vector</span><span style=3D"color: rgb(0, 136, 0);">&lt;foo&gt;</s=
pan><span style=3D"color: rgb(0, 0, 0);">=C2=A0a=C2=A0</span><span style=3D=
"color: rgb(102, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0, 0);">=
=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">...;</span><span styl=
e=3D"color: rgb(0, 0, 0);"><br>l2</span><span style=3D"color: rgb(102, 102,=
 0);">:</span><span style=3D"color: rgb(0, 0, 0);"><br>extended_vector</spa=
n><span style=3D"color: rgb(0, 136, 0);">&lt;foo&gt;</span><span style=3D"c=
olor: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">=
&amp;</span><font color=3D"#000000">=C2=A0b=C2=A0<span style=3D"color: rgb(=
102, 102, 0);">=3D</span>=C2=A0extend_cast<span style=3D"color: rgb(102, 10=
2, 0);">&lt;</span>extended_vector<span style=3D"color: rgb(0, 136, 0);">&l=
t;<wbr>foo&gt;</span><span style=3D"color: rgb(102, 102, 0);">&amp;&gt;</sp=
an>=C2=A0<span style=3D"color: rgb(102, 102, 0);">(</span>a<span style=3D"c=
olor: rgb(102, 102, 0);">);</span><br>b<span style=3D"color: rgb(102, 102, =
0);">.</span>bar<span style=3D"color: rgb(102, 102, 0);">();</span><br><spa=
n style=3D"color: rgb(0, 0, 136);">goto</span>=C2=A0l1<span style=3D"color:=
 rgb(102, 102, 0);">;</span></font></code></div><br>So what happens after t=
he goto statement? Do we call the destructor of b and not the destructor of=
 a? What happens if we do &quot;goto l2;&quot; instead? How do we &quot;une=
xtend&quot; the class?</div></div></blockquote><div><div><br></div><div>Ref=
erences don&#39;t use destructors.=C2=A0 They don&#39;t have ownership.</di=
v></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: =
1ex;"><div dir=3D"ltr"><div>Reinterpreting the data of the class as though =
it were another type is done with reinterpret_cast, I&#39;m not sure what t=
he extend cast is supposed to other than make that more defined behavior. B=
ut IIRC, reinterpret cast has defined behavior for certain POD types.</div>=
<div><br></div><div>What it seems to me that you want is a type safe versio=
n of reinterpret cast. But that raises some issues, we can&#39;t check &quo=
t;binary compatibility&quot;, only whether or not either the POD layout is =
the same, or the types share some base in some way.</div><div><br></div><di=
v>Lets say we only check the binary layout, so you could cast a std::string=
 to a extended_vector&lt;char&gt; because both look something like:</div><d=
iv><div style=3D"border-width: 1px; border-style: solid; border-color: rgb(=
187, 187, 187); background-color: rgb(250, 250, 250); word-wrap: break-word=
;"><code><span style=3D"color: rgb(0, 0, 136);">struct</span><span style=3D=
"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);=
">{</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0size_t</span><span sty=
le=3D"color: rgb(102, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);=
">=C2=A0size_t</span><span style=3D"color: rgb(102, 102, 0);">;</span><span=
 style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0=
, 136);">char</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span=
 style=3D"color: rgb(102, 102, 0);">*;</span><span style=3D"color: rgb(0, 0=
, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">};</span></cod=
e></div>But they are not compatible. (trailing 0s, SSO could be different, =
etc.) So instead of casting based on binary layout, lets say you cast based=
 upon the base class.</div><div>Now what do we do when we try to &quot;exte=
nd_cast&quot; something that wasn&#39;t meant to be extended? Like for exam=
ple having your iterator inherit from your const_iterator. Thus, you could =
extend_cast a const_iterator to an iterator. Doesn&#39;t sound legit to me.=
 That&#39;s why I suggest a different syntax. I&#39;m going to improve on i=
t a bit here.</div><div><br></div><div><div style=3D"border-width: 1px; bor=
der-style: solid; border-color: rgb(187, 187, 187); background-color: rgb(2=
50, 250, 250); word-wrap: break-word;"><code><span style=3D"color: rgb(0, 0=
, 136);">class</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0foo=C2=A0</=
span><span style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color:=
 rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">...</=
span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color=
: rgb(102, 102, 0);">};</span><span style=3D"color: rgb(0, 0, 0);"><br><br>=
</span><span style=3D"color: rgb(0, 0, 136);">class</span><span style=3D"co=
lor: rgb(0, 0, 0);">=C2=A0bar=C2=A0</span><span style=3D"color: rgb(102, 10=
2, 0);">:</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span sty=
le=3D"color: rgb(0, 0, 136);">public</span><span style=3D"color: rgb(0, 0, =
0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">&amp;</span><spa=
n style=3D"color: rgb(0, 0, 0);">foo<br></span><span style=3D"color: rgb(10=
2, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0</span>=
<span style=3D"color: rgb(0, 0, 136);">public</span><span style=3D"color: r=
gb(102, 102, 0);">:</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 b=
ar</span><span style=3D"color: rgb(102, 102, 0);">(...)</span><span style=
=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, =
0);">{</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0=C2=A0</span><span =
style=3D"color: rgb(102, 102, 0);">}</span><span style=3D"color: rgb(0, 0, =
0);"><br></span><span style=3D"color: rgb(102, 102, 0);">}</span><font colo=
r=3D"#000000"><span style=3D"color: rgb(102, 102, 0);">;</span></font></cod=
e></div><br>Now the only rule is that bar must initialize the reference to =
foo. This provides a transparent forwarding of the public methods of foo to=
 a user of the bar class, and also provides any additional methods of bar.<=
/div><div>It&#39;s also possible that ~bar could &quot;convert back&quot; a=
 temporary change.=C2=A0</div><div><br></div><div>While this is mostly poss=
ible using proxy objects, you have to manually forward every member functio=
n. Inheriting from a reference solves the problem in a neater way.</div><di=
v>It would also have other uses, consider these theoretical example wrapper=
s around a C string:</div><div><div style=3D"border-width: 1px; border-styl=
e: solid; border-color: rgb(187, 187, 187); background-color: rgb(250, 250,=
 250); word-wrap: break-word;"><code><span style=3D"color: rgb(0, 0, 136);"=
>class</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0local_c_string<br><=
/span><span style=3D"color: rgb(102, 102, 0);">:</span><span style=3D"color=
: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">public=
</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"col=
or: rgb(102, 102, 0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);">c_s=
tring<br></span><span style=3D"color: rgb(102, 102, 0);">{</span><span styl=
e=3D"color: rgb(0, 0, 0);"><br>=C2=A0=C2=A0</span><span style=3D"color: rgb=
(0, 0, 136);">mutable</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0size=
_t len</span><span style=3D"color: rgb(102, 102, 0);">;</span><span style=
=3D"color: rgb(0, 0, 0);"><br>=C2=A0=C2=A0</span><span style=3D"color: rgb(=
0, 0, 136);">mutable</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</spa=
n><span style=3D"color: rgb(0, 0, 136);">bool</span><span style=3D"color: r=
gb(0, 0, 0);">=C2=A0len_cached</span><span style=3D"color: rgb(102, 102, 0)=
;">;</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"c=
olor: rgb(0, 0, 136);">public</span><span style=3D"color: rgb(102, 102, 0);=
">:</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0local_c_string</sp=
an><span style=3D"color: rgb(102, 102, 0);">(</span><font color=3D"#000000"=
>c_string=C2=A0<span style=3D"color: rgb(102, 102, 0);">&amp;</span>=C2=A0i=
</font><span style=3D"color: rgb(102, 102, 0);">)</span><span style=3D"colo=
r: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">:</=
span><span style=3D"color: rgb(0, 0, 0);">=C2=A0c_string</span><span style=
=3D"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(0, 0, 0);">=
i</span><span style=3D"color: rgb(102, 102, 0);">),</span><span style=3D"co=
lor: rgb(0, 0, 0);">=C2=A0len</span><span style=3D"color: rgb(102, 102, 0);=
">(</span><span style=3D"color: rgb(0, 102, 102);">0</span><span style=3D"c=
olor: rgb(102, 102, 0);">),</span><span style=3D"color: rgb(0, 0, 0);">=C2=
=A0len_cached</span><span style=3D"color: rgb(102, 102, 0);">(</span><span =
style=3D"color: rgb(0, 102, 102);">0</span><span style=3D"color: rgb(102, 1=
02, 0);">)</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span st=
yle=3D"color: rgb(102, 102, 0);">{}</span><span style=3D"color: rgb(0, 0, 0=
);"><br>=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">bool</span><spa=
n style=3D"color: rgb(0, 0, 0);">=C2=A0size</span><span style=3D"color: rgb=
(102, 102, 0);">()</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span>=
<span style=3D"color: rgb(0, 0, 136);">const</span><span style=3D"color: rg=
b(0, 0, 0);"><br></span><font color=3D"#666600"><span style=3D"color: rgb(0=
, 0, 0);">=C2=A0</span>{<span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=
=A0</span><span style=3D"color: rgb(0, 0, 136);">if</span>(<span style=3D"c=
olor: rgb(0, 0, 0);">=C2=A0len_cached</span>)<span style=3D"color: rgb(0, 0=
, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">return</span><sp=
an style=3D"color: rgb(0, 0, 0);">=C2=A0len</span>;<span style=3D"color: rg=
b(0, 0, 0);"><br>=C2=A0 =C2=A0len=C2=A0</span>=3D<span style=3D"color: rgb(=
0, 0, 0);">=C2=A0strlen</span>();<span style=3D"color: rgb(0, 0, 0);"><br>=
=C2=A0 =C2=A0</span><span style=3D"color: rgb(0, 0, 136);">return</span><sp=
an style=3D"color: rgb(0, 0, 0);">=C2=A0len</span>;<span style=3D"color: rg=
b(0, 0, 0);"><br>=C2=A0</span>}<span style=3D"color: rgb(0, 0, 0);"><br></s=
pan></font><span style=3D"color: rgb(0, 0, 0);">=C2=A0local_c_string=C2=A0<=
/span><span style=3D"color: rgb(102, 102, 0);">&amp;</span><span style=3D"c=
olor: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">op=
erator</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=
=3D"color: rgb(102, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0, 0);=
">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">(</span><span style=
=3D"color: rgb(0, 0, 0);">c_string=C2=A0</span><span style=3D"color: rgb(10=
2, 102, 0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0other</=
span><span style=3D"color: rgb(102, 102, 0);">)</span><span style=3D"color:=
 rgb(0, 0, 0);"><br>=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">{=
</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0</span><span s=
tyle=3D"color: rgb(0, 0, 136);">static_cast</span><span style=3D"color: rgb=
(102, 102, 0);">&lt;</span><span style=3D"color: rgb(0, 0, 0);">c_string</s=
pan><span style=3D"color: rgb(102, 102, 0);">&amp;&gt;(*</span><font color=
=3D"#000000"><span style=3D"color: rgb(0, 0, 136);">this</span><span style=
=3D"color: rgb(102, 102, 0);">)</span>=C2=A0<span style=3D"color: rgb(102, =
102, 0);">=3D</span>=C2=A0other<span style=3D"color: rgb(102, 102, 0);">;</=
span><br>=C2=A0 =C2=A0len_cached=C2=A0<span style=3D"color: rgb(102, 102, 0=
);">=3D</span>=C2=A0<span style=3D"color: rgb(0, 0, 136);">false</span><spa=
n style=3D"color: rgb(102, 102, 0);">;</span></font><span style=3D"color: r=
gb(0, 0, 0);"><br>=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">}</=
span><span style=3D"color: rgb(0, 0, 0);"><br><br></span><span style=3D"col=
or: rgb(102, 102, 0);">};</span><span style=3D"color: rgb(0, 0, 0);"><br></=
span></code></div><br>The compiler would be able to detect when the referen=
ces are equal and thus optimize out the declaration, and it doesn&#39;t get=
 into any of the wackyness of extend cast.</div><div><br></div><div>To avoi=
d the pitfall of thinking that the derived class actually inherits from the=
 reference class, maybe the syntax should be different?</div><div><br></div=
><div><div style=3D"border-width: 1px; border-style: solid; border-color: r=
gb(187, 187, 187); background-color: rgb(250, 250, 250); word-wrap: break-w=
ord;"><code><span style=3D"color: rgb(0, 0, 136);">typename</span><span sty=
le=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102=
, 0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);">local_c_string loca=
lstr</span><span style=3D"color: rgb(102, 102, 0);">(</span><span style=3D"=
color: rgb(0, 0, 0);">str</span><span style=3D"color: rgb(102, 102, 0);">);=
</span><font color=3D"#666600"></font></code></div><br>This would help dist=
inguish between objects that are references and objects that contain refere=
nces. The typename is required because I think the grammar might be ambiguo=
us in templates otherwise.</div><div>But I&#39;m not sure if that&#39;s an =
optimal solution, since it would cause reference objects to be treated diff=
erently from objects that contain references. To make sure it evaluates cor=
rectly using templates, we could say that the full type of a reference obje=
ct is &quot;&amp;foo&quot; rather than the class name &quot;foo&quot;. So t=
hen:</div><div><div style=3D"border-width: 1px; border-style: solid; border=
-color: rgb(187, 187, 187); background-color: rgb(250, 250, 250); word-wrap=
: break-word;"><code><font color=3D"#660066"><span style=3D"color: rgb(0, 0=
, 136);">class</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0bar<br>=C2=
=A0</span><span style=3D"color: rgb(102, 102, 0);">:</span><span style=3D"c=
olor: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">pu=
blic</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D=
"color: rgb(102, 102, 0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);"=
>baz<br></span><span style=3D"color: rgb(102, 102, 0);">{</span><span style=
=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color: rgb(102, 102, 0)=
;">...</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D=
"color: rgb(102, 102, 0);">};</span><span style=3D"color: rgb(0, 0, 0);"><b=
r><br></span><span style=3D"color: rgb(0, 0, 136);">template</span><span st=
yle=3D"color: rgb(102, 102, 0);">&lt;</span><span style=3D"color: rgb(0, 0,=
 136);">typename</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0T</span><=
span style=3D"color: rgb(102, 102, 0);">&gt;</span><span style=3D"color: rg=
b(0, 0, 0);"><br></span><span style=3D"color: rgb(0, 0, 136);">class</span>=
<span style=3D"color: rgb(0, 0, 0);">=C2=A0foo<br></span><span style=3D"col=
or: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"><br></s=
pan><span style=3D"color: rgb(102, 102, 0);">...</span><span style=3D"color=
: rgb(0, 0, 0);"><br></span><span style=3D"color: rgb(0, 0, 136);">public</=
span><span style=3D"color: rgb(102, 102, 0);">:</span><span style=3D"color:=
 rgb(0, 0, 0);"><br>=C2=A0=C2=A0</span><span style=3D"color: rgb(0, 0, 136)=
;">using</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0value_type=C2=A0<=
/span><span style=3D"color: rgb(102, 102, 0);">=3D</span><span style=3D"col=
or: rgb(0, 0, 0);">=C2=A0T</span><span style=3D"color: rgb(102, 102, 0);">;=
</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color=
: rgb(102, 102, 0);">};</span><span style=3D"color: rgb(0, 0, 0);"><br><br>=
foo=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">&lt;</span><span s=
tyle=3D"color: rgb(0, 0, 136);">typename</span><span style=3D"color: rgb(10=
2, 102, 0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0bar</sp=
an><span style=3D"color: rgb(102, 102, 0);">&gt;</span><span style=3D"color=
: rgb(0, 0, 0);">=C2=A0a</span><span style=3D"color: rgb(102, 102, 0);">;</=
span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color: =
rgb(136, 0, 0);">//=C2=A0</span></font><span style=3D"background-color: rgb=
(255, 255, 255); font-family: Arial, Helvetica, sans-serif;"><span style=3D=
"color: rgb(136, 0, 0);">Here, a::value_type would be &quot;&amp;bar&quot; =
rather than &quot;bar&quot; (not to be confused with bar&amp;)</span><span =
style=3D"color: rgb(0, 0, 0);"><br><br>bar b</span><span style=3D"color: rg=
b(102, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);"><br></span><s=
pan style=3D"color: rgb(136, 0, 0);">// This line would cause a compilation=
 error. bar is not a typename.</span><span style=3D"color: rgb(0, 0, 0);"><=
br></span><span style=3D"color: rgb(102, 102, 0);">&amp;</span><span style=
=3D"color: rgb(0, 0, 0);">bar b</span><span style=3D"color: rgb(102, 102, 0=
);">;</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"=
color: rgb(136, 0, 0);">// Also an error because it&#39;s not clear whether=
 &amp; is the unary operator &amp; or a typename</span><span style=3D"color=
: rgb(0, 0, 0);"><br></span><span style=3D"color: rgb(0, 0, 136);">typename=
</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"col=
or: rgb(102, 102, 0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);">=C2=
=A0bar b=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">(</span><span=
 style=3D"color: rgb(0, 0, 0);">a</span><span style=3D"color: rgb(102, 102,=
 0);">);</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=
=3D"color: rgb(136, 0, 0);">// Not an error, typename&amp; used.</span></sp=
an></code></div><br><br></div><div>This prevents them from being accidental=
ly used where a normal object is expected, but retains the ability to use t=
hem in templates without requiring special syntax.</div><div>If there is a =
case where you want the default operator =3D etc. to function like it would=
 for an object containing a reference rather than an reference object , you=
 could apply the static/inline keyword:</div><div><br></div><div><div style=
=3D"border-width: 1px; border-style: solid; border-color: rgb(187, 187, 187=
); background-color: rgb(250, 250, 250); word-wrap: break-word;"><code><fon=
t color=3D"#660066"><span style=3D"color: rgb(0, 0, 136);">class</span><spa=
n style=3D"color: rgb(0, 0, 0);">=C2=A0foo<br>=C2=A0</span><span style=3D"c=
olor: rgb(102, 102, 0);">:</span><span style=3D"color: rgb(0, 0, 0);">=C2=
=A0</span><span style=3D"color: rgb(0, 0, 136);">static</span><span style=
=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, =
0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);">bar<br></span><span s=
tyle=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0=
);"><br></span><span style=3D"color: rgb(102, 102, 0);">...</span><span sty=
le=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color: rgb(102, 102, =
0);">};</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=
=3D"color: rgb(136, 0, 0);">// Functions like an object containing a refere=
nce and the type name is &quot;foo&quot;</span><span style=3D"color: rgb(0,=
 0, 0);"><br><br></span></font><span style=3D"color: rgb(0, 0, 136);">class=
</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0baz<br>=C2=A0</span><span=
 style=3D"color: rgb(102, 102, 0);">:</span><span style=3D"color: rgb(0, 0,=
 0);">=C2=A0</span><font color=3D"#000088">inline</font><span style=3D"colo=
r: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">&am=
p;</span><span style=3D"color: rgb(0, 0, 0);">bar<br></span><span style=3D"=
color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=
</span><span style=3D"color: rgb(102, 102, 0);">...</span><span style=3D"co=
lor: rgb(0, 0, 0);"><br></span><span style=3D"color: rgb(102, 102, 0);">};<=
/span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color:=
 rgb(136, 0, 0);">// Functions like a reference instead of an object. Type =
name is &quot;&amp;baz&quot;</span><font color=3D"#660066"><span style=3D"c=
olor: rgb(0, 0, 0);"><br></span></font></code></div><br>I&#39;m not sure wh=
ether the default should be static or inline though. Maybe always require i=
t explicitly?</div></div></blockquote><div><br></div>I like the idea of inh=
eriting from a reference type.  This would allow extending a type safely, a=
nd even allow adding member variables (though without any members, it could=
 be considered just as an retyped alias object).  As it is inheriting from =
a reference, it has no ownership of the underlying referenced object, so it=
&#39;s destruction would leave the underlying object intact.<br><br>I&#39;m=
 going to have to look at your examples again, because I think our trains o=
f thought diverged.  I&#39;m thinking that the new object that derived from=
 a reference object could be used just like a regular object. and doesn&#39=
;t really need any special handling.  However, the developer would have to =
be aware of the decoupled lifespans.<br><br>Also, not sure why you put the =
&amp; before the typename.  Why not after, as it seems more natural?<div cl=
ass=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-c=
olor: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap=
: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> X<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"colo=
r: #008;" class=3D"styled-by-prettify">public</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">~</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">X</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">cout </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #080;" class=3D"styled-by-prettify">&quot;~X()&quot;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">endl</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </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><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> Y </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">public</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> X</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">public</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 Y</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">delete</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// This can never be made</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 Y</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">X</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> x</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> X</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;(</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">x</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">{}</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">// Required signature. =C2=A0This would be default impl though.</s=
pan><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">Y</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">cout </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">&lt;&lt;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">=
&quot;~Y()&quot;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt=
;&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">endl</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-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-pr=
ettify">class</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> Z </span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">public</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> X</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">public</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 =C2=A0 Z</span><span style=3D"color: #660;" class=
=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">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">delete</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 =C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// T=
his can never be made</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 Z</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">X</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">&amp;&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> x</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> X</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">&amp;&amp;(</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">x</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">{}</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// Requir=
ed signature. =C2=A0This would be default impl though.</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">Z</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">()</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: #000;" class=3D"styled-by-pr=
ettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">cout <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #080;" class=3D"styled-by-prettify">&quot;~Z()&quot;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">endl</span><span style=3D"color: #660;" c=
lass=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: #000;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> main</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 X 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 </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 Y y0</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-pret=
tify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
=C2=A0 =C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-prettif=
y">// Y&#39;s destructor is called, but X&#39;s is not</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 Y y1</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">X</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">()};</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> =C2=A0</span><span style=3D"color: #800;" =
class=3D"styled-by-prettify">// Invalid</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 </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 Z z0</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">x</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> =C2=A0 =C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-pre=
ttify">// Invalid</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 Z z1</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">X</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>()};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=
=A0</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// Z&#3=
9;s destructor is called, but X&#39;s is not</span><span style=3D"color: #0=
00;" 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;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">0</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: #800;" class=3D"styled-by-prettify">// X&#39;s d=
estructor is called</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><b=
r></span></div></code></div><div><br>Haven&#39;t completely thought through=
 if there should be a difference between an lvalue and rvalue reference inh=
eritance though.=C2=A0 Unnecessary?</div><br><br><br><br><br><br><br>ss<br>=
<br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/758cd43b-2c3f-4f6e-91bb-4fbca9aad79c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/758cd43b-2c3f-4f6e-91bb-4fbca9aad79c=
%40isocpp.org</a>.<br />

------=_Part_196_549565035.1513610308171--

------=_Part_195_392883858.1513610308169--

.


Author: Ryan Nicholl <r.p.nicholl@gmail.com>
Date: Sat, 30 Dec 2017 16:55:07 -0800 (PST)
Raw View
------=_Part_31531_851465234.1514681707628
Content-Type: multipart/alternative;
 boundary="----=_Part_31532_345312078.1514681707629"

------=_Part_31532_345312078.1514681707629
Content-Type: text/plain; charset="UTF-8"

I don't think you could inherit from an rvalue reference since "named"
values are lvalues, then your "rvalue" would be an lvalue.

That's not to say you couldn't have "rvalue_proxy" and "lvalue_proxy"
classes with different overloaded constructors. (and corresponding usages
of delete).

I'm suggesting the usage of the static/inline specifiers in order to change
the way operator= is defaulted. A "static" reference inheritance would
cause operator= to reassign new references (like reassigning
std::reference_wrapper) and an "inline" inheritance would assign the
referenced values. Perhaps that distinction made by static is unsafe, since
it could cause a reference to the base class to act very differently from
the derived, but I don't really see a way to make it work more like a
struct { foo & a; } would other than this.

I thought & foo would be easier to parse than foo &, but I don't see any
reason why inheriting from foo & would be a problem.





On Monday, December 18, 2017 at 10:18:28 AM UTC-5, Jack Adrian Zappa wrote:
>
> On Thursday, December 14, 2017 at 3:40:58 PM UTC-5, Ryan Nicholl wrote:
>>
>> Well, allowing inheritance from a reference would give the following
>> advantages:
>>
>> First, we can get the same advantages of extend cast, because the
>> compiler could see that they have the same address, and thus the compiler
>> doesn't need to create a separate variable.
>>
>> Extend cast has a couple of issues. First, if the compiler ONLY checks
>> the binary layout, then you could convert a vector to an extended string by
>> accident.
>>
>> If the compiler instead checks that the base class is the same, we
>> basically have a cast that allows us to cast vector A to B, only the memory
>> of A is destroyed?
>> Or is it? What actually happens to the vector object? Is it now a vector?
>> or is it something else? What is the type of that object now?
>> What happens if you do:
>> l1:
>> vector<foo> a = ...;
>> l2:
>> extended_vector<foo> & b = extend_cast<extended_vector<foo>&> (a);
>> b.bar();
>> goto l1;
>>
>> So what happens after the goto statement? Do we call the destructor of b
>> and not the destructor of a? What happens if we do "goto l2;" instead? How
>> do we "unextend" the class?
>>
>
> References don't use destructors.  They don't have ownership.
>
> Reinterpreting the data of the class as though it were another type is
>> done with reinterpret_cast, I'm not sure what the extend cast is supposed
>> to other than make that more defined behavior. But IIRC, reinterpret cast
>> has defined behavior for certain POD types.
>>
>> What it seems to me that you want is a type safe version of reinterpret
>> cast. But that raises some issues, we can't check "binary compatibility",
>> only whether or not either the POD layout is the same, or the types share
>> some base in some way.
>>
>> Lets say we only check the binary layout, so you could cast a std::string
>> to a extended_vector<char> because both look something like:
>> struct { size_t; size_t; char *; };
>> But they are not compatible. (trailing 0s, SSO could be different, etc.)
>> So instead of casting based on binary layout, lets say you cast based upon
>> the base class.
>> Now what do we do when we try to "extend_cast" something that wasn't
>> meant to be extended? Like for example having your iterator inherit from
>> your const_iterator. Thus, you could extend_cast a const_iterator to an
>> iterator. Doesn't sound legit to me. That's why I suggest a different
>> syntax. I'm going to improve on it a bit here.
>>
>> class foo { ... };
>>
>> class bar : public &foo
>> {
>>  public:
>>   bar(...) {  }
>> };
>>
>> Now the only rule is that bar must initialize the reference to foo. This
>> provides a transparent forwarding of the public methods of foo to a user of
>> the bar class, and also provides any additional methods of bar.
>> It's also possible that ~bar could "convert back" a temporary change.
>>
>> While this is mostly possible using proxy objects, you have to manually
>> forward every member function. Inheriting from a reference solves the
>> problem in a neater way.
>> It would also have other uses, consider these theoretical example
>> wrappers around a C string:
>> class local_c_string
>> : public &c_string
>> {
>>   mutable size_t len;
>>   mutable bool len_cached;
>> public:
>>  local_c_string(c_string & i) : c_string(i), len(0), len_cached(0) {}
>>  bool size() const
>>  {
>>    if( len_cached) return len;
>>    len = strlen();
>>    return len;
>>  }
>>  local_c_string & operator = (c_string & other)
>>  {
>>    static_cast<c_string&>(*this) = other;
>>    len_cached = false;
>>  }
>>
>> };
>>
>> The compiler would be able to detect when the references are equal and
>> thus optimize out the declaration, and it doesn't get into any of the
>> wackyness of extend cast.
>>
>> To avoid the pitfall of thinking that the derived class actually inherits
>> from the reference class, maybe the syntax should be different?
>>
>> typename &local_c_string localstr(str);
>>
>> This would help distinguish between objects that are references and
>> objects that contain references. The typename is required because I think
>> the grammar might be ambiguous in templates otherwise.
>> But I'm not sure if that's an optimal solution, since it would cause
>> reference objects to be treated differently from objects that contain
>> references. To make sure it evaluates correctly using templates, we could
>> say that the full type of a reference object is "&foo" rather than the
>> class name "foo". So then:
>> class bar
>>  : public &baz
>> {
>> ...
>> };
>>
>> template<typename T>
>> class foo
>> {
>> ...
>> public:
>>   using value_type = T;
>> };
>>
>> foo <typename& bar> a;
>> // Here, a::value_type would be "&bar" rather than "bar" (not to be
>> confused with bar&)
>>
>> bar b;
>> // This line would cause a compilation error. bar is not a typename.
>> &bar b;
>> // Also an error because it's not clear whether & is the unary operator &
>> or a typename
>> typename & bar b (a);
>> // Not an error, typename& used.
>>
>>
>> This prevents them from being accidentally used where a normal object is
>> expected, but retains the ability to use them in templates without
>> requiring special syntax.
>> If there is a case where you want the default operator = etc. to function
>> like it would for an object containing a reference rather than an reference
>> object , you could apply the static/inline keyword:
>>
>> class foo
>>  : static &bar
>> {
>> ...
>> };
>> // Functions like an object containing a reference and the type name is
>> "foo"
>>
>> class baz
>>  : inline &bar
>> {
>> ...
>> };
>> // Functions like a reference instead of an object. Type name is "&baz"
>>
>> I'm not sure whether the default should be static or inline though. Maybe
>> always require it explicitly?
>>
>
> I like the idea of inheriting from a reference type. This would allow
> extending a type safely, and even allow adding member variables (though
> without any members, it could be considered just as an retyped alias
> object). As it is inheriting from a reference, it has no ownership of the
> underlying referenced object, so it's destruction would leave the
> underlying object intact.
>
> I'm going to have to look at your examples again, because I think our
> trains of thought diverged. I'm thinking that the new object that derived
> from a reference object could be used just like a regular object. and
> doesn't really need any special handling. However, the developer would have
> to be aware of the decoupled lifespans.
>
> Also, not sure why you put the & before the typename. Why not after, as it
> seems more natural?
> class X
> {
>   public:
>     ~X() { std::cout << "~X()" << std::endl; }
> };
>
> class Y : public X&
> {
>   public:
>     Y() = delete;      // This can never be made
>     Y(X& x) : X&(x) {} // Required signature.  This would be default impl
> though.
>     ~Y() { std::cout << "~Y()" << std::endl; }
> };
>
> class Z : public X&&
> {
>   public:
>     Z() = delete;        // This can never be made
>     Z(X&& x) : X&&(x) {} // Required signature.  This would be default
> impl though.
>     ~Z() { std::cout << "~Z()" << std::endl; }
> };
>
> int main()
> {
>   X x;
>   {
>     Y y0{x};    // Y's destructor is called, but X's is not
>     Y y1{X()};  // Invalid
>   }
>
>   {
>     Z z0{x};    // Invalid
>     Z z1{X()};  // Z's destructor is called, but X's is not
>   }
>   return 0; // X's destructor is called
> }
>
>
> Haven't completely thought through if there should be a difference between
> an lvalue and rvalue reference inheritance though.  Unnecessary?
>
>
>
>
>
>
>
> ss
>
>

--
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/b992c7ea-e5ae-47e3-ae6c-e6d83449fd62%40isocpp.org.

------=_Part_31532_345312078.1514681707629
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I don&#39;t think you could inherit from an rvalue referen=
ce since &quot;named&quot; values are lvalues, then your &quot;rvalue&quot;=
 would be an lvalue.<br><br>That&#39;s not to say you couldn&#39;t have &qu=
ot;rvalue_proxy&quot; and &quot;lvalue_proxy&quot; classes with different o=
verloaded constructors. (and corresponding usages of delete).<br><br>I&#39;=
m suggesting the usage of the static/inline specifiers in order to change t=
he way  operator=3D is defaulted. A &quot;static&quot; reference inheritanc=
e would cause operator=3D to reassign new references (like reassigning std:=
:reference_wrapper) and an &quot;inline&quot; inheritance would assign the =
referenced values. Perhaps that distinction made by static is unsafe, since=
 it could cause a reference to the base class to act very differently from =
the derived, but I don&#39;t really see a way to make it work more like a s=
truct { foo &amp; a; } would other than this.<br><br>I thought &amp; foo wo=
uld be easier to parse than foo &amp;, but I don&#39;t see any reason why i=
nheriting from foo &amp; would be a problem.<br><br><br><br><br><br>On Mond=
ay, December 18, 2017 at 10:18:28 AM UTC-5, Jack Adrian Zappa wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Thursday, Decembe=
r 14, 2017 at 3:40:58 PM UTC-5, Ryan Nicholl wrote:<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"><div dir=3D"ltr">Well, allowing inheritance from =
a reference would give the following advantages:<br><br>First, we can get t=
he same advantages of extend cast, because the compiler could see that they=
 have the same address, and thus the compiler doesn&#39;t need to create a =
separate variable.<div><br></div><div>Extend cast has a couple of issues. F=
irst, if the compiler ONLY checks the binary layout, then you could convert=
 a vector to an extended string by accident.</div><div><br></div><div>If th=
e compiler instead checks that the base class is the same, we basically hav=
e a cast that allows us to cast vector A to B, only the memory of A is dest=
royed?</div><div>Or is it? What actually happens to the vector object? Is i=
t now a vector? or is it something else? What is the type of that object no=
w?</div><div>What happens if you do:</div><div><div style=3D"border-width:1=
px;border-style:solid;border-color:rgb(187,187,187);background-color:rgb(25=
0,250,250);word-wrap:break-word"><code><span style=3D"color:rgb(0,0,0)">l1<=
/span><span style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb=
(0,0,0)"><br>vector</span><span style=3D"color:rgb(0,136,0)">&lt;foo&gt;</s=
pan><span style=3D"color:rgb(0,0,0)">=C2=A0a=C2=A0</span><span style=3D"col=
or:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span>=
<span style=3D"color:rgb(102,102,0)">...;</span><span style=3D"color:rgb(0,=
0,0)"><br>l2</span><span style=3D"color:rgb(102,102,0)">:</span><span style=
=3D"color:rgb(0,0,0)"><br>extended_vector</span><span style=3D"color:rgb(0,=
136,0)">&lt;foo&gt;</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><sp=
an style=3D"color:rgb(102,102,0)">&amp;</span><font color=3D"#000000">=C2=
=A0b=C2=A0<span style=3D"color:rgb(102,102,0)">=3D</span>=C2=A0<wbr>extend_=
cast<span style=3D"color:rgb(102,102,0)">&lt;</span>extended_vector<span st=
yle=3D"color:rgb(0,136,0)">&lt;<wbr>foo&gt;</span><span style=3D"color:rgb(=
102,102,0)">&amp;&gt;</span>=C2=A0<span style=3D"color:rgb(102,102,0)">(</s=
pan>a<span style=3D"color:rgb(102,102,0)">);</span><br>b<span style=3D"colo=
r:rgb(102,102,0)">.</span>bar<span style=3D"color:rgb(102,102,0)">();</span=
><br><span style=3D"color:rgb(0,0,136)">goto</span>=C2=A0l1<span style=3D"c=
olor:rgb(102,102,0)">;</span></font></code></div><br>So what happens after =
the goto statement? Do we call the destructor of b and not the destructor o=
f a? What happens if we do &quot;goto l2;&quot; instead? How do we &quot;un=
extend&quot; the class?</div></div></blockquote><div><div><br></div><div>Re=
ferences don&#39;t use destructors.=C2=A0 They don&#39;t have ownership.</d=
iv></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><=
div dir=3D"ltr"><div>Reinterpreting the data of the class as though it were=
 another type is done with reinterpret_cast, I&#39;m not sure what the exte=
nd cast is supposed to other than make that more defined behavior. But IIRC=
, reinterpret cast has defined behavior for certain POD types.</div><div><b=
r></div><div>What it seems to me that you want is a type safe version of re=
interpret cast. But that raises some issues, we can&#39;t check &quot;binar=
y compatibility&quot;, only whether or not either the POD layout is the sam=
e, or the types share some base in some way.</div><div><br></div><div>Lets =
say we only check the binary layout, so you could cast a std::string to a e=
xtended_vector&lt;char&gt; because both look something like:</div><div><div=
 style=3D"border-width:1px;border-style:solid;border-color:rgb(187,187,187)=
;background-color:rgb(250,250,250);word-wrap:break-word"><code><span style=
=3D"color:rgb(0,0,136)">struct</span><span style=3D"color:rgb(0,0,0)">=C2=
=A0</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color=
:rgb(0,0,0)">=C2=A0size_t</span><span style=3D"color:rgb(102,102,0)">;</spa=
n><span style=3D"color:rgb(0,0,0)">=C2=A0size_t</span><span style=3D"color:=
rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span=
 style=3D"color:rgb(0,0,136)">char</span><span style=3D"color:rgb(0,0,0)">=
=C2=A0</span><span style=3D"color:rgb(102,102,0)"><wbr>*;</span><span style=
=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(102,102,0)">};<=
/span></code></div>But they are not compatible. (trailing 0s, SSO could be =
different, etc.) So instead of casting based on binary layout, lets say you=
 cast based upon the base class.</div><div>Now what do we do when we try to=
 &quot;extend_cast&quot; something that wasn&#39;t meant to be extended? Li=
ke for example having your iterator inherit from your const_iterator. Thus,=
 you could extend_cast a const_iterator to an iterator. Doesn&#39;t sound l=
egit to me. That&#39;s why I suggest a different syntax. I&#39;m going to i=
mprove on it a bit here.</div><div><br></div><div><div style=3D"border-widt=
h:1px;border-style:solid;border-color:rgb(187,187,187);background-color:rgb=
(250,250,250);word-wrap:break-word"><code><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)">=C2=A0foo=C2=A0</span><span =
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)">=C2=
=A0</span><span style=3D"color:rgb(102,102,0)">...</span><span style=3D"col=
or:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(102,102,0)">};</span><=
span style=3D"color:rgb(0,0,0)"><br><br></span><span style=3D"color:rgb(0,0=
,136)">class</span><span style=3D"color:rgb(0,0,0)">=C2=A0bar=C2=A0</span><=
span style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)=
">=C2=A0</span><span style=3D"color:rgb(0,0,136)">public</span><span style=
=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(102,102,0)">&am=
p;</span><span style=3D"color:rgb(0,0,0)">foo<br></span><span style=3D"colo=
r:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0</span=
><span style=3D"color:rgb(0,0,136)">public</span><span style=3D"color:rgb(1=
02,102,0)">:</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 bar</span><s=
pan style=3D"color:rgb(102,102,0)">(...)</span><span style=3D"color:rgb(0,0=
,0)">=C2=A0</span><span style=3D"color:rgb(102,102,0)">{</span><span style=
=3D"color:rgb(0,0,0)">=C2=A0=C2=A0</span><span style=3D"color:rgb(102,102,0=
)">}</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color=
:rgb(102,102,0)">}</span><font color=3D"#000000"><span style=3D"color:rgb(1=
02,102,0)">;</span></font></code></div><br>Now the only rule is that bar mu=
st initialize the reference to foo. This provides a transparent forwarding =
of the public methods of foo to a user of the bar class, and also provides =
any additional methods of bar.</div><div>It&#39;s also possible that ~bar c=
ould &quot;convert back&quot; a temporary change.=C2=A0</div><div><br></div=
><div>While this is mostly possible using proxy objects, you have to manual=
ly forward every member function. Inheriting from a reference solves the pr=
oblem in a neater way.</div><div>It would also have other uses, consider th=
ese theoretical example wrappers around a C string:</div><div><div style=3D=
"border-width:1px;border-style:solid;border-color:rgb(187,187,187);backgrou=
nd-color:rgb(250,250,250);word-wrap:break-word"><code><span style=3D"color:=
rgb(0,0,136)">class</span><span style=3D"color:rgb(0,0,0)">=C2=A0local_c_st=
ring<br></span><span style=3D"color:rgb(102,102,0)">:</span><span style=3D"=
color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(0,0,136)">public</s=
pan><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(=
102,102,0)">&amp;</span><span style=3D"color:rgb(0,0,0)">c_string<br></span=
><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,=
0)"><br>=C2=A0=C2=A0</span><span style=3D"color:rgb(0,0,136)">mutable</span=
><span style=3D"color:rgb(0,0,0)">=C2=A0size_t len</span><span style=3D"col=
or:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0=C2=
=A0</span><span style=3D"color:rgb(0,0,136)">mutable</span><span style=3D"c=
olor:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(0,0,136)">bool</span=
><span style=3D"color:rgb(0,0,0)">=C2=A0len_cached</span><span style=3D"col=
or:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(0,0,136)">public</span><span style=3D"color:rgb(102,10=
2,0)">:</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0local_c_string</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><font color=3D"#000000">c_s=
tring=C2=A0<span style=3D"color:rgb(102,102,0)">&amp;</span>=C2=A0i</font><=
span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)=
">=C2=A0</span><span style=3D"color:rgb(102,102,0)"><wbr>:</span><span styl=
e=3D"color:rgb(0,0,0)">=C2=A0c_string</span><span style=3D"color:rgb(102,10=
2,0)">(</span><span style=3D"color:rgb(0,0,0)">i</span><span style=3D"color=
:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,0)">=C2=A0len</span>=
<span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,102=
,102)">0</span><span style=3D"color:rgb(102,102,0)">),</span><span style=3D=
"color:rgb(0,0,0)">=C2=A0len_<wbr>cached</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,102,102)">0</span><span style=
=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)">=C2=A0</=
span><span style=3D"color:rgb(102,102,0)">{}</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0</span><span style=3D"color:rgb(0,0,136)">bool</span><sp=
an style=3D"color:rgb(0,0,0)">=C2=A0size</span><span style=3D"color:rgb(102=
,102,0)">()</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=
=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"><br></=
span><font color=3D"#666600"><span style=3D"color:rgb(0,0,0)">=C2=A0</span>=
{<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0</span><span style=3D"co=
lor:rgb(0,0,136)">if</span>(<span style=3D"color:rgb(0,0,0)">=C2=A0len_cach=
ed</span>)<span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"colo=
r:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)">=C2=A0len</sp=
an>;<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0len=C2=A0</span>=3D<s=
pan style=3D"color:rgb(0,0,0)">=C2=A0strlen</span>();<span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 =C2=A0</span><span style=3D"color:rgb(0,0,136)">retur=
n</span><span style=3D"color:rgb(0,0,0)">=C2=A0len</span>;<span style=3D"co=
lor:rgb(0,0,0)"><br>=C2=A0</span>}<span style=3D"color:rgb(0,0,0)"><br></sp=
an></font><span style=3D"color:rgb(0,0,0)">=C2=A0local_c_string=C2=A0</span=
><span style=3D"color:rgb(102,102,0)">&amp;</span><span style=3D"color:rgb(=
0,0,0)">=C2=A0</span><span style=3D"color:rgb(0,0,136)">operator</span><spa=
n style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(102,102,=
0)">=3D</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"=
color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)"><wbr>c_strin=
g=C2=A0</span><span style=3D"color:rgb(102,102,0)">&amp;</span><span style=
=3D"color:rgb(0,0,0)">=C2=A0other</span><span style=3D"color:rgb(102,102,0)=
">)</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0</span><span style=3D"=
color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =
=C2=A0</span><span style=3D"color:rgb(0,0,136)">static_cast</span><span sty=
le=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,0,0)">c_s=
tring</span><span style=3D"color:rgb(102,102,0)">&amp;&gt;(*</span><font co=
lor=3D"#000000"><span style=3D"color:rgb(0,0,136)">this</span><span style=
=3D"color:rgb(102,102,0)">)</span><wbr>=C2=A0<span style=3D"color:rgb(102,1=
02,0)">=3D</span>=C2=A0other<span style=3D"color:rgb(102,102,0)">;</span><b=
r>=C2=A0 =C2=A0len_cached=C2=A0<span style=3D"color:rgb(102,102,0)">=3D</sp=
an>=C2=A0<span style=3D"color:rgb(0,0,136)">false</span><span style=3D"colo=
r:rgb(102,102,0)">;</span></font><span style=3D"color:rgb(0,0,0)"><br>=C2=
=A0</span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color=
:rgb(0,0,0)"><br><br></span><span style=3D"color:rgb(102,102,0)">};</span><=
span style=3D"color:rgb(0,0,0)"><br></span></code></div><br>The compiler wo=
uld be able to detect when the references are equal and thus optimize out t=
he declaration, and it doesn&#39;t get into any of the wackyness of extend =
cast.</div><div><br></div><div>To avoid the pitfall of thinking that the de=
rived class actually inherits from the reference class, maybe the syntax sh=
ould be different?</div><div><br></div><div><div style=3D"border-width:1px;=
border-style:solid;border-color:rgb(187,187,187);background-color:rgb(250,2=
50,250);word-wrap:break-word"><code><span style=3D"color:rgb(0,0,136)">type=
name</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"col=
or:rgb(102,102,0)">&amp;</span><span style=3D"color:rgb(0,0,0)">local_c_str=
ing localstr</span><span style=3D"color:rgb(102,102,0)">(</span><span style=
=3D"color:rgb(0,0,0)">str</span><span style=3D"color:rgb(102,102,0)">);</sp=
an><font color=3D"#666600"></font></code></div><br>This would help distingu=
ish between objects that are references and objects that contain references=
.. The typename is required because I think the grammar might be ambiguous i=
n templates otherwise.</div><div>But I&#39;m not sure if that&#39;s an opti=
mal solution, since it would cause reference objects to be treated differen=
tly from objects that contain references. To make sure it evaluates correct=
ly using templates, we could say that the full type of a reference object i=
s &quot;&amp;foo&quot; rather than the class name &quot;foo&quot;. So then:=
</div><div><div style=3D"border-width:1px;border-style:solid;border-color:r=
gb(187,187,187);background-color:rgb(250,250,250);word-wrap:break-word"><co=
de><font color=3D"#660066"><span style=3D"color:rgb(0,0,136)">class</span><=
span style=3D"color:rgb(0,0,0)">=C2=A0bar<br>=C2=A0</span><span style=3D"co=
lor:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><=
span style=3D"color:rgb(0,0,136)">public</span><span style=3D"color:rgb(0,0=
,0)">=C2=A0</span><span style=3D"color:rgb(102,102,0)">&amp;</span><span st=
yle=3D"color:rgb(0,0,0)">baz<br></span><span style=3D"color:rgb(102,102,0)"=
>{</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(102,102,0)">...</span><span style=3D"color:rgb(0,0,0)"><br></span><span =
style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><b=
r><br></span><span style=3D"color:rgb(0,0,136)">template</span><span style=
=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,0,136)">typ=
ename</span><span style=3D"color:rgb(0,0,0)">=C2=A0T</span><span style=3D"c=
olor:rgb(102,102,0)">&gt;</span><span style=3D"color:rgb(0,0,0)"><br></span=
><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(0,=
0,0)">=C2=A0foo<br></span><span style=3D"color:rgb(102,102,0)">{</span><spa=
n style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)=
">...</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"colo=
r:rgb(0,0,136)">public</span><span style=3D"color:rgb(102,102,0)">:</span><=
span style=3D"color:rgb(0,0,0)"><br>=C2=A0=C2=A0</span><span style=3D"color=
:rgb(0,0,136)">using</span><span style=3D"color:rgb(0,0,0)">=C2=A0value_typ=
e=C2=A0</span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D=
"color:rgb(0,0,0)">=C2=A0T</span><span style=3D"color:rgb(102,102,0)">;</sp=
an><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102=
,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br><br>foo=C2=A0</span>=
<span style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,=
0,136)">typename</span><span style=3D"color:rgb(102,102,0)">&amp;</span><sp=
an style=3D"color:rgb(0,0,0)">=C2=A0bar</span><span style=3D"color:rgb(102,=
102,0)">&gt;</span><span style=3D"color:rgb(0,0,0)">=C2=A0a</span><span sty=
le=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(136,0,0)">//=C2=A0</span></font><span style=
=3D"background-color:rgb(255,255,255);font-family:Arial,Helvetica,sans-seri=
f"><span style=3D"color:rgb(136,0,0)">Here, a::value_type would be &quot;&a=
mp;bar&quot; rather than &quot;bar&quot; (not to be confused with bar&amp;)=
</span><span style=3D"color:rgb(0,0,0)"><br><br>bar b</span><span style=3D"=
color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br></span><=
span style=3D"color:rgb(136,0,0)">// This line would cause a compilation er=
ror. bar is not a typename.</span><span style=3D"color:rgb(0,0,0)"><br></sp=
an><span style=3D"color:rgb(102,102,0)">&amp;</span><span style=3D"color:rg=
b(0,0,0)">bar b</span><span style=3D"color:rgb(102,102,0)">;</span><span st=
yle=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(136,0,0)">// A=
lso an error because it&#39;s not clear whether &amp; is the unary operator=
 &amp; or a typename</span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(0,0,136)">typename</span><span style=3D"color:rgb(0,0,=
0)">=C2=A0</span><span style=3D"color:rgb(102,102,0)">&amp;</span><span sty=
le=3D"color:rgb(0,0,0)">=C2=A0bar b=C2=A0</span><span style=3D"color:rgb(10=
2,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a</span><span style=3D"c=
olor:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br></span><=
span style=3D"color:rgb(136,0,0)">// Not an error, typename&amp; used.</spa=
n></span></code></div><br><br></div><div>This prevents them from being acci=
dentally used where a normal object is expected, but retains the ability to=
 use them in templates without requiring special syntax.</div><div>If there=
 is a case where you want the default operator =3D etc. to function like it=
 would for an object containing a reference rather than an reference object=
 , you could apply the static/inline keyword:</div><div><br></div><div><div=
 style=3D"border-width:1px;border-style:solid;border-color:rgb(187,187,187)=
;background-color:rgb(250,250,250);word-wrap:break-word"><code><font color=
=3D"#660066"><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"=
color:rgb(0,0,0)">=C2=A0foo<br>=C2=A0</span><span style=3D"color:rgb(102,10=
2,0)">:</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"=
color:rgb(0,0,136)">static</span><span style=3D"color:rgb(0,0,0)">=C2=A0</s=
pan><span style=3D"color:rgb(102,102,0)">&amp;</span><span style=3D"color:r=
gb(0,0,0)">bar<br></span><span style=3D"color:rgb(102,102,0)">{</span><span=
 style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)"=
>...</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color=
:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br></span><span=
 style=3D"color:rgb(136,0,0)">// Functions like an object containing a refe=
rence and the type name is &quot;foo&quot;</span><span style=3D"color:rgb(0=
,0,0)"><br><br></span></font><span style=3D"color:rgb(0,0,136)">class</span=
><span style=3D"color:rgb(0,0,0)">=C2=A0baz<br>=C2=A0</span><span style=3D"=
color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span=
><font color=3D"#000088">inline</font><span style=3D"color:rgb(0,0,0)">=C2=
=A0</span><span style=3D"color:rgb(102,102,0)">&amp;</span><span style=3D"c=
olor:rgb(0,0,0)">bar<br></span><span style=3D"color:rgb(102,102,0)">{</span=
><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,1=
02,0)">...</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D=
"color:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br></span=
><span style=3D"color:rgb(136,0,0)">// Functions like a reference instead o=
f an object. Type name is &quot;&amp;baz&quot;</span><font color=3D"#660066=
"><span style=3D"color:rgb(0,0,0)"><br></span></font></code></div><br>I&#39=
;m not sure whether the default should be static or inline though. Maybe al=
ways require it explicitly?</div></div></blockquote><div><br></div>I like t=
he idea of inheriting from a reference type.  This would allow extending a =
type safely, and even allow adding member variables (though without any mem=
bers, it could be considered just as an retyped alias object).  As it is in=
heriting from a reference, it has no ownership of the underlying referenced=
 object, so it&#39;s destruction would leave the underlying object intact.<=
br><br>I&#39;m going to have to look at your examples again, because I thin=
k our trains of thought diverged.  I&#39;m thinking that the new object tha=
t derived from a reference object could be used just like a regular object.=
 and doesn&#39;t really need any special handling.  However, the developer =
would have to be aware of the decoupled lifespans.<br><br>Also, not sure wh=
y you put the &amp; before the typename.  Why not after, as it seems more n=
atural?<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">class</span><span style=3D"color:#000"> X<br=
></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 </span><span style=3D"color:#008">public</span><span style=3D"color:=
#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color:#660">~</span><span style=3D"color:#000">X</span><span style=3D=
"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">{</span><span style=3D"color:#000"> std</span><span style=3D"color=
:#660">::</span><span style=3D"color:#000">cout </span><span style=3D"color=
:#660">&lt;&lt;</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#080">&quot;~X()&quot;</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">&lt;&lt;</span><span style=3D"color:#000"> std</span><sp=
an style=3D"color:#660">::</span><span style=3D"color:#000">endl</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><span st=
yle=3D"color:#008">class</span><span style=3D"color:#000"> Y </span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">public</span><span style=3D"color:#000"> X</span><span styl=
e=3D"color:#660">&amp;</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><sp=
an style=3D"color:#008">public</span><span style=3D"color:#660">:</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 Y</span><span style=3D"color:#660=
">()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008">del=
ete</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> =
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">// This can never be =
made</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 Y</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">X</span><span style=3D"c=
olor:#660">&amp;</span><span style=3D"color:#000"> x</span><span style=3D"c=
olor:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">:</span><span style=3D"color:#000"> X</span><span style=3D"color:#660=
">&amp;(</span><span style=3D"color:#000">x</span><span style=3D"color:#660=
">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{}<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#800">// Requ=
ired signature. =C2=A0This would be default impl though.</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">~</span=
><span style=3D"color:#000">Y</span><span style=3D"color:#660">()</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span st=
yle=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span sty=
le=3D"color:#000">cout </span><span style=3D"color:#660">&lt;&lt;</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#080">&quot;~Y()&quot;=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&lt;&l=
t;</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">:=
:</span><span style=3D"color:#000">endl</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">}</span=
><span style=3D"color:#000"><br></span><span style=3D"color:#660">};</span>=
<span style=3D"color:#000"><br><br></span><span style=3D"color:#008">class<=
/span><span style=3D"color:#000"> Z </span><span style=3D"color:#660">:</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">public</sp=
an><span style=3D"color:#000"> X</span><span style=3D"color:#660">&amp;&amp=
;</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:#00=
8">public</span><span style=3D"color:#660">:</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 Z</span><span style=3D"color:#660">()</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">delete</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"> =C2=A0 =C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#800">// This can never be made</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 Z</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">X</span><span style=3D"color:#660">&am=
p;&amp;</span><span style=3D"color:#000"> x</span><span style=3D"color:#660=
">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">:</=
span><span style=3D"color:#000"> X</span><span style=3D"color:#660">&amp;&a=
mp;(</span><span style=3D"color:#000">x</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#800">// Required=
 signature. =C2=A0This would be default impl though.</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">~</span><spa=
n style=3D"color:#000">Z</span><span style=3D"color:#660">()</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">cout </span><span style=3D"color:#660">&lt;&lt;</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#080">&quot;~Z()&quot;</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">&lt;&lt;=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#000">endl</span><span style=3D"color:#660">;</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">}</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">};</span><s=
pan style=3D"color:#000"><br><br></span><span style=3D"color:#008">int</spa=
n><span style=3D"color:#000"> main</span><span style=3D"color:#660">()</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span>=
<span style=3D"color:#000"><br>=C2=A0 X x</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#=
660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 Y y0</span><span =
style=3D"color:#660">{</span><span style=3D"color:#000">x</span><span style=
=3D"color:#660">};</span><span style=3D"color:#000"> =C2=A0 =C2=A0</span><s=
pan style=3D"color:#800">// Y&#39;s destructor is called, but X&#39;s is no=
t</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 Y y1</span><span style=
=3D"color:#660">{</span><span style=3D"color:#000">X</span><span style=3D"c=
olor:#660">()};</span><span style=3D"color:#000"> =C2=A0</span><span style=
=3D"color:#800">// Invalid</span><span style=3D"color:#000"><br>=C2=A0 </sp=
an><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br>=
=C2=A0 </span><span style=3D"color:#660">{</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 Z z0</span><span style=3D"color:#660">{</span><span styl=
e=3D"color:#000">x</span><span style=3D"color:#660">};</span><span style=3D=
"color:#000"> =C2=A0 =C2=A0</span><span style=3D"color:#800">// Invalid</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 Z z1</span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000">X</span><span style=3D"color:=
#660">()};</span><span style=3D"color:#000"> =C2=A0</span><span style=3D"co=
lor:#800">// Z&#39;s destructor is called, but X&#39;s is not</span><span s=
tyle=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">retur=
n</span><span style=3D"color:#000"> </span><span style=3D"color:#066">0</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#800">// X&#39;s destructor is called</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br><br></span></div></code></div><div><br>Haven&#39;t comp=
letely thought through if there should be a difference between an lvalue an=
d rvalue reference inheritance though.=C2=A0 Unnecessary?</div><br><br><br>=
<br><br><br><br>ss<br><br></div></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b992c7ea-e5ae-47e3-ae6c-e6d83449fd62%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b992c7ea-e5ae-47e3-ae6c-e6d83449fd62=
%40isocpp.org</a>.<br />

------=_Part_31532_345312078.1514681707629--

------=_Part_31531_851465234.1514681707628--

.