Topic: Proposal: std::view and std::optional_view (Re:


Author: joseph.thomson@gmail.com
Date: Mon, 10 Oct 2016 20:10:37 -0700 (PDT)
Raw View
------=_Part_3078_864378770.1476155437835
Content-Type: multipart/alternative;
 boundary="----=_Part_3079_1513849083.1476155437836"

------=_Part_3079_1513849083.1476155437836
Content-Type: text/plain; charset=UTF-8

Hi,

This message highlights my thoughts about so-called "smart references" and
how best to support such a concept in the standard library.

I am usually excited by any upcoming or proposed additions to C++, but the operator
dot proposal
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4173.pdf>
concerns me. It strikes me as adding significant complexity to the language
to support what amounts to a bit of syntactic sugar. Of course, given that
the proposal essentially adds support for compile-time function overriding,
I'm sure it could be used to do all sorts of "clever" things, but I digress.

I do see the need for official support for "smart references" in C++.
Modern C++ orthodoxy says that raw pointers should be avoided in high-level
code. C++ has always recommended std::string over C-style strings and
std::vector over C-style dynamic arrays. The smart pointers std::unique_ptr
and std::shared_ptr are now established for resource management, and
std::array for statically sized arrays. The upcoming std::optional replaces
some potential uses of raw pointers, std::string_view means we no longer
need to deal with raw pointers into std::string objects, and the proposed
std::array_view will do the same for arrays.

However, one use of raw pointers still remains: as non-owning references.
When I say references, I don't mean just C++ references; I mean any use of
C++ pointers or C++ references to refer to an object which is not owned. A
common pattern is to use a C++ reference where a reference is mandatory,
and a C++ pointer where a reference is optional (using nullptr as the
"missing" state).

  void foo(bar const& mandatory);
  void foo(bar const* optional);

However, there are a few shortcomings to this approach:

   1. It lacks semantics. The meaning of a raw pointer is overloaded; are
   we passing a reference, an array, an "iterator", an "owning" pointer, or a
   string (in the case of char const*)? Even if we know it is a reference,
   is it really optional? Some people don't like representing references using
   C++ references, so they used pointers that cannot be null instead. The GSL
   is addressing this somewhat with the gsl::not_null annotation, but this
   is hardly optimal. Speaking of references, they also have overloaded
   meaning: passing by reference can be for performance, or because a
   reference is genuinely needed (and maybe stored somewhere).
   2. C++ references cannot be reassigned. I understand this is one of the
   motivating forces behind the operator dot proposal. I agree it is a big
   problem.

What we need are some wrapper types which can represent references
(mandatory or optional) to arbitrary objects. One proposal
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282> already
exists which kind of addresses this need: std::observer_ptr (a.k.a. The
World's Dumbest Smart Pointer). This is nice because it conveys meaning (it
"observes"; it doesn't "own"), but it falls short in a few other areas.
Firstly, it doesn't support mandatory references (pointers can be null).
Secondly, it still has "pointer" semantics. I would like my smart
references to have "reference" semantics; in other words, I do not want to
have to enter the realm of C++ pointers; I do not want to have to do this:

  std::observer_ptr<int> o = &i; // address-of operator: yuck!

The problem is that std::observer_ptr is an "observing" pointer modelled on
the "owning" smart pointers, hence why is is kind of dumb. I propose that
we need wrappers designed from the ground up to model some kind of
"reference" concept. However, since std::ref is already taken, and for
other reasons which should become apparent later, I suggest not using the
term "reference". We could follow std::observer_ptr and use the term
"observer", but I feel that the name "view" is more appropriate, having
been coined by std::string_view as a term for something which is a
non-owning reference to another object. Thus, I suggest std::view:

  std::view<int> v = i; // no pointer semantics: yay!

But, I hear you say, don't we need the operator dot proposal to get our
"reference-y" semantics? Well, to get C++ reference semantics, yes we do.
However, it is not required. Consider this:

  std::view<int> v = i;
  v = j; // reassignment of the view
  *v = 42; // assignment of the referenced object

This has the advantage that assignment of the view and assignment of the
referenced object are clearly disambiguated; there is no need to change the
language, and there is less potential for confusing. But, but, I hear you
protest, this is pointer semantics! Indeed, the operator dot proposal
mentions this as a motivating factor. However, there is already precedent
for non-pointer usage of operator* and operator-> in std::optional:

  std::optional<int> o = i;
  o = j; // reassignment of the optional
  *o = 42; // assignment of the underlying object

Indeed, std::view would have the exact same semantics as std::optional.
Thus, we have a "smart reference" type which requires no change to the
language, has no null/missing state, supports reassignment, has non-pointer
semantics, and has usage patterns consistent with other types already in
the standard library. Optional references can also be implemented naturally:

  std::optional_view<int> o; // can be default constructed
  o = i; // reassignment of the optional
  o = std::view<int>(j); // optional views can be assigned from views, but
not vice-versa

  if (o) {
    *o = 42; // assignment of the underlying object
  }

  o = std::nullopt; // reuse of existing library features: yay!

I think this is pretty neat. And none of this required support for
overloading operator dot. Indeed, I feel that the the ambiguous nature of
operator= for a type which overloads operator dot may be a red flag that
something is amiss. However, I'm sure this has been discussed at length,
and perhaps the operator dot proposal is orthogonal to what I am suggesting
here. I just wanted to show that we can already address a number of
concerns without adding complexity to the language, and in my opinion, far
more cleanly than any solution involving operator dot.

One final thought: would the existence of std::optional_view make
std::observer_ptr redundant? My feeling is "perhaps", but I wouldn't be
surprised the answer were "no".

Thanks for taking the time to read my musings. Please let me know your
opinions, and if anything like this has been suggested before.

Kind regards,

Joseph Thomson

--
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/41be9d41-d160-4be8-bd1c-a662e108211d%40isocpp.org.

------=_Part_3079_1513849083.1476155437836
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hi,<br><br>This message highlights my thoughts about so-ca=
lled &quot;smart references&quot; and how best to support such a concept in=
 the standard library.<br><br>I am usually excited by any upcoming or propo=
sed additions to C++, but the <a href=3D"http://www.open-std.org/jtc1/sc22/=
wg21/docs/papers/2014/n4173.pdf">operator dot proposal</a> concerns me. It =
strikes me as adding significant complexity to the language to support what=
 amounts to a bit of syntactic sugar. Of course, given that the proposal es=
sentially adds support for compile-time function overriding, I&#39;m sure i=
t could be used to do all sorts of &quot;clever&quot; things, but I digress=
..<br><br>I do see the need for official support for &quot;smart references&=
quot; in C++. Modern C++ orthodoxy says that raw pointers should be avoided=
 in high-level code. C++ has always recommended <span style=3D"font-family:=
 courier new,monospace;">std::string</span> over C-style strings and <span =
style=3D"font-family: courier new,monospace;">std::vector</span> over C-sty=
le dynamic arrays. The smart pointers <span style=3D"font-family: courier n=
ew,monospace;">std::unique_ptr</span> and <span style=3D"font-family: couri=
er new,monospace;">std::shared_ptr</span> are now established for resource =
management, and <span style=3D"font-family: courier new,monospace;">std::ar=
ray</span> for statically sized arrays. The upcoming <span style=3D"font-fa=
mily: courier new,monospace;">std::optional</span> replaces some potential =
uses of raw pointers, <span style=3D"font-family: courier new,monospace;">s=
td::string_view</span> means we no longer need to deal with raw pointers in=
to <span style=3D"font-family: courier new,monospace;">std::string</span> o=
bjects, and the proposed <span style=3D"font-family: courier new,monospace;=
">std::array_view</span> will do the same for arrays.<br><br>However, one u=
se of raw pointers still remains: as non-owning references. When I say refe=
rences, I don&#39;t mean just C++ references; I mean any use of C++ pointer=
s or C++ references to refer to an object which is not owned. A common patt=
ern is to use a C++ reference where a reference is mandatory, and a C++ poi=
nter where a reference is optional (using <span style=3D"font-family: couri=
er new,monospace;">nullptr</span> as the &quot;missing&quot; state).<br><br=
><span style=3D"font-family: courier new,monospace;">=C2=A0 void foo(bar co=
nst&amp; mandatory);<br>=C2=A0 void foo(bar const* optional);</span><br><br=
>However, there are a few shortcomings to this approach:<br><ol><li>It lack=
s semantics. The meaning of a raw pointer is overloaded; are we passing a r=
eference, an array, an &quot;iterator&quot;, an &quot;owning&quot; pointer,=
 or a string (in the case of <span style=3D"font-family: courier new,monosp=
ace;">char const*</span>)? Even if we know it is a reference, is it really =
optional? Some people don&#39;t like representing references using C++ refe=
rences, so they used pointers that cannot be null instead. The GSL is addre=
ssing this somewhat with the <span style=3D"font-family: courier new,monosp=
ace;">gsl::not_null</span> annotation, but this is hardly optimal. Speaking=
 of references, they also have overloaded meaning: passing by reference can=
 be for performance, or because a reference is genuinely needed (and maybe =
stored somewhere).</li><li>C++ references cannot be reassigned. I understan=
d this is one of the motivating forces behind the operator dot proposal. I =
agree it is a big problem.<br></li></ol>What we need are some wrapper types=
 which can represent references (mandatory or optional) to arbitrary object=
s. <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282=
">One proposal</a> already exists which kind of addresses this need: <span =
style=3D"font-family: courier new,monospace;">std::observer_ptr</span> (a.k=
..a. The World&#39;s Dumbest Smart Pointer). This is nice because it conveys=
 meaning (it &quot;observes&quot;; it doesn&#39;t &quot;own&quot;), but it =
falls short in a few other areas. Firstly, it doesn&#39;t support mandatory=
 references (pointers can be null). Secondly, it still has &quot;pointer&qu=
ot; semantics. I would like my smart references to have &quot;reference&quo=
t; semantics; in other words, I do not want to have to enter the realm of C=
++ pointers; I do not want to have to do this:<br><br><span style=3D"font-f=
amily: courier new,monospace;">=C2=A0 std::observer_ptr&lt;int&gt; o =3D &a=
mp;i; // address-of operator: yuck!</span><br><br>The problem is that <span=
 style=3D"font-family: courier new,monospace;">std::observer_ptr</span> is =
an &quot;observing&quot; pointer modelled on the &quot;owning&quot; smart p=
ointers, hence why is is kind of dumb. I propose that we need wrappers desi=
gned from the ground up to model some kind of &quot;reference&quot; concept=
.. However, since <span style=3D"font-family: courier new,monospace;">std::r=
ef</span> is already taken, and for other reasons which should become appar=
ent later, I suggest not using the term &quot;reference&quot;. We could fol=
low <span style=3D"font-family: courier new,monospace;">std::observer_ptr</=
span> and use the term &quot;observer&quot;, but I feel that the name &quot=
;view&quot; is more appropriate, having been coined by <span style=3D"font-=
family: courier new,monospace;">std::string_view</span> as a term for somet=
hing which is a non-owning reference to another object. Thus, I suggest <sp=
an style=3D"font-family: courier new,monospace;">std::view</span>:<br><br><=
span style=3D"font-family: courier new,monospace;">=C2=A0 std::view&lt;int&=
gt; v =3D i; // no pointer semantics: yay!</span><br><br>But, I hear you sa=
y, don&#39;t we need the operator dot proposal to get our &quot;reference-y=
&quot; semantics? Well, to get C++ reference semantics, yes we do. However,=
 it is not required. Consider this:<br><br><span style=3D"font-family: cour=
ier new,monospace;">=C2=A0 std::view&lt;int&gt; v =3D i;<br>=C2=A0 v =3D j;=
 // reassignment of the view<br>=C2=A0 *v =3D 42; // assignment of the refe=
renced object<br></span><br>This has the advantage that assignment of the v=
iew and assignment of the referenced object are clearly disambiguated; ther=
e is no need to change the language, and there is less potential for confus=
ing. But, but, I hear you protest, this is pointer semantics! Indeed, the o=
perator dot proposal mentions this as a motivating factor. However, there i=
s already precedent for non-pointer usage of <span style=3D"font-family: co=
urier new,monospace;">operator*</span> and <span style=3D"font-family: cour=
ier new,monospace;">operator-&gt;</span> in <span style=3D"font-family: cou=
rier new,monospace;">std::optional</span>: <br><br><span style=3D"font-fami=
ly: courier new,monospace;">=C2=A0 std::optional&lt;int&gt; o =3D i;<br>=C2=
=A0 o =3D j; // reassignment of the optional<br>=C2=A0 *o =3D 42; // assign=
ment of the underlying object<br></span><br>Indeed, <span style=3D"font-fam=
ily: courier new,monospace;">std::view</span> would have the exact same sem=
antics as <span style=3D"font-family: courier new,monospace;">std::optional=
</span>. Thus, we have a &quot;smart reference&quot; type which requires no=
 change to the language, has no null/missing state, supports reassignment, =
has non-pointer semantics, and has usage patterns consistent with other typ=
es already in the standard library. Optional references can also be impleme=
nted naturally:<br><br><span style=3D"font-family: courier new,monospace;">=
=C2=A0 std::optional_view&lt;int&gt; o; // can be default constructed<br>=
=C2=A0 o =3D i; // reassignment of the optional<br>=C2=A0 o =3D std::view&l=
t;int&gt;(j); // optional views can be assigned from views, but not vice-ve=
rsa<br><br>=C2=A0 if (o) {<br>=C2=A0=C2=A0=C2=A0 *o =3D 42; // assignment o=
f the underlying object<br>=C2=A0 }<br>=C2=A0 <br>=C2=A0 o =3D std::nullopt=
; // reuse of existing library features: yay!<br></span><br>I think this is=
 pretty neat. And none of this required support for overloading operator do=
t. Indeed, I feel that the the ambiguous nature of <span style=3D"font-fami=
ly: courier new,monospace;">operator=3D</span> for a type which overloads o=
perator dot may be a red flag that something is amiss. However, I&#39;m sur=
e this has been discussed at length, and perhaps the operator dot proposal =
is orthogonal to what I am suggesting here. I just wanted to show that we c=
an already address a number of concerns without adding complexity to the la=
nguage, and in my opinion, far more cleanly than any solution involving ope=
rator dot.<br><br>One final thought: would the existence of <span style=3D"=
font-family: courier new,monospace;">std::optional_view</span> make <span s=
tyle=3D"font-family: courier new,monospace;">std::observer_ptr</span> redun=
dant? My feeling is &quot;perhaps&quot;, but I wouldn&#39;t be surprised th=
e answer were &quot;no&quot;.<br><br>Thanks for taking the time to read my =
musings. Please let me know your opinions, and if anything like this has be=
en suggested before.<br><br>Kind regards,<br><br>Joseph Thomson<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/41be9d41-d160-4be8-bd1c-a662e108211d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/41be9d41-d160-4be8-bd1c-a662e108211d=
%40isocpp.org</a>.<br />

------=_Part_3079_1513849083.1476155437836--

------=_Part_3078_864378770.1476155437835--

.


Author: "D. B." <db0451@gmail.com>
Date: Tue, 11 Oct 2016 07:07:29 +0100
Raw View
--089e01228c120eb93c053e90b16d
Content-Type: text/plain; charset=UTF-8

You said "I would like my smart references to have "reference" semantics;
in other words, I do not want to have to enter the realm of C++ pointers; I
do not want to have to do this:"

But both of your examples seem to require - and rationalise - such. What am
I missing? OK, so they're more pointer _linguistics_ than semantics, but
it's still pointer syntax.

Conversely, the point of the recent smart reference proposals, AFAICT -
other than making writing code a lot easier in supportive situations - is
that they could be transparently incorporated into generic code that would
work with plain reference.

To require pointer syntax I think defeats this and makes such proposals a
moot point, since we could implement our own pretty trivilly where required
- and indeed, often do. What operator dot et al propose is a way to save us
that work by adding required scaffolding to the language itself, whch makes
it moot.

--
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/CACGiwhFSd4an44mf30efNb-5_Q_1Ee6ct8q%2BQG54BEgqcLosdg%40mail.gmail.com.

--089e01228c120eb93c053e90b16d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><div>You said &quot;I would like my smart=20
references to have &quot;reference&quot; semantics; in other words, I do no=
t want=20
to have to enter the realm of C++ pointers; I do not want to have to do=20
this:&quot;<br><br></div>But both of your examples seem to require - and ra=
tionalise - such. What am I missing? OK, so they&#39;re more pointer _lingu=
istics_ than semantics, but it&#39;s still pointer syntax.<br><br></div>Con=
versely, the point of the recent smart reference proposals, AFAICT - other =
than making writing code a lot easier in supportive situations - is that th=
ey could be transparently incorporated into generic code that would work wi=
th plain reference.<br><br>To require pointer syntax I think defeats this a=
nd makes such proposals a moot point, since we could implement our own pret=
ty trivilly where required - and indeed, often do. What operator dot et al =
propose is a way to save us that work by adding required scaffolding to the=
 language itself, whch makes it moot.<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/CACGiwhFSd4an44mf30efNb-5_Q_1Ee6ct8q%=
2BQG54BEgqcLosdg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CACGiwhFSd4an44=
mf30efNb-5_Q_1Ee6ct8q%2BQG54BEgqcLosdg%40mail.gmail.com</a>.<br />

--089e01228c120eb93c053e90b16d--

.


Author: joseph.thomson@gmail.com
Date: Mon, 10 Oct 2016 23:54:44 -0700 (PDT)
Raw View
------=_Part_2968_1958495499.1476168884379
Content-Type: multipart/alternative;
 boundary="----=_Part_2969_1973707989.1476168884379"

------=_Part_2969_1973707989.1476168884379
Content-Type: text/plain; charset=UTF-8



On Tuesday, 11 October 2016 14:07:32 UTC+8, D. B. wrote:
>
> You said "I would like my smart references to have "reference" semantics;
> in other words, I do not want to have to enter the realm of C++ pointers; I
> do not want to have to do this:"
>
> But both of your examples seem to require - and rationalise - such. What
> am I missing? OK, so they're more pointer _linguistics_ than semantics, but
> it's still pointer syntax.
>

Yes, operator* and operator-> are pointer syntax in that they are defined
for pointer types, but I provided std::optional as an example of a
non-pointer type in the standard library which uses these operators to show
that they have taken on new meaning. Perhaps in modern C++ they would be
better referred to as "wrapper syntax". When I said I wanted to avoid
pointer semantics, I meant that I didn't want people to think of the type
as a pointer (semantics = meaning). If you can assign from a pointer, it
suggests that the type in some way models a pointer.

  std::view<int> v = &i; // not what I want (rhs is of type int*)
  std::view<int> v = i; // what I want (rhs is of type int&)


>
> Conversely, the point of the recent smart reference proposals, AFAICT -
> other than making writing code a lot easier in supportive situations - is
> that they could be transparently incorporated into generic code that would
> work with plain reference.
>

I'm not sure what you mean by "supportive situations". And I would like to
see some real examples of where it is useful to be able to write generic
code using reference syntax (operator dot). I'm not denying such examples
exist, I just can't think of any myself. And it's possible to write generic
code that operates on all wrapper types.

  template <typename T>
  void call_foo_checked(T const& v) {
    if (v) {
      v->foo();
    }
  }

  bar b;

  call_foo_checked(std::make_unique<bar>(b));
  call_foo_checked(std::make_shared<bar>(b));
  call_foo_checked(std::make_optional(b));
  call_foo_checked(std::make_view(b)); // operator bool returns true; check
will be optimized away
  call_foo_checked(std::make_optional_view(b));


> To require pointer syntax I think defeats this and makes such proposals a
> moot point, since we could implement our own pretty trivilly where required
> - and indeed, often do. What operator dot et al propose is a way to save us
> that work by adding required scaffolding to the language itself, whch makes
> it moot.
>

As I just explained, it's wrapper syntax, not just pointer syntax. And the
idea is not necessarily to avoid specific syntax; it's to model a concept
(in this case, views on objects) in a natural way that meshes well with the
rest of the language and standard library. I don't like the operator dot
proposal because it does not feel natural; it feels forced. That said, my
aim here is not to prevent the proposal from being accepted; I'm just
trying to provide an alternative when it comes to modelling the
reference/view concept.

And many features of the standard library could be trivially implemented;
there are reasons for including something in the standard library other
than "it's hard to implement".

--
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/ef844f2c-8a17-44d0-b1e9-9c6ff2cdbda7%40isocpp.org.

------=_Part_2969_1973707989.1476168884379
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, 11 October 2016 14:07:32 UTC+8, D. B. =
 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"><div><=
div>You said &quot;I would like my smart=20
references to have &quot;reference&quot; semantics; in other words, I do no=
t want=20
to have to enter the realm of C++ pointers; I do not want to have to do=20
this:&quot;<br><br></div>But both of your examples seem to require - and ra=
tionalise - such. What am I missing? OK, so they&#39;re more pointer _lingu=
istics_ than semantics, but it&#39;s still pointer syntax.<br></div></div><=
/blockquote><div><br>Yes, <span style=3D"font-family: courier new,monospace=
;">operator*</span> and <span style=3D"font-family: courier new,monospace;"=
>operator-&gt;</span> are pointer syntax in that they are defined for point=
er types, but I provided <span style=3D"font-family: courier new,monospace;=
">std::optional</span> as an example of a non-pointer type in the standard =
library which uses these operators to show that they have taken on new mean=
ing. Perhaps in modern C++ they would be better referred to as &quot;wrappe=
r syntax&quot;. When I said I wanted to avoid pointer semantics, I meant th=
at I didn&#39;t want people to think of the type as a pointer (semantics =
=3D meaning). If you can assign from a pointer, it suggests that the type i=
n some way models a pointer.<br><br><span style=3D"font-family: courier new=
,monospace;">=C2=A0 std::view&lt;int&gt; v =3D &amp;i; // not what I want (=
rhs is of type int*)<br>=C2=A0 std::view&lt;int&gt; v =3D i; // what I want=
 (rhs is of type int&amp;)</span><br>=C2=A0<br></div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div>Conversely, the poin=
t of the recent smart reference proposals, AFAICT - other than making writi=
ng code a lot easier in supportive situations - is that they could be trans=
parently incorporated into generic code that would work with plain referenc=
e.<br></div></blockquote><div><br>I&#39;m not sure what you mean by &quot;s=
upportive situations&quot;. And I would like to see some real examples of w=
here it is useful to be able to write generic code using reference syntax (=
operator dot). I&#39;m not denying such examples exist, I just can&#39;t th=
ink of any myself. And it&#39;s possible to write generic code that operate=
s on all wrapper types.<br><br><span style=3D"font-family: courier new,mono=
space;">=C2=A0 template &lt;typename T&gt;<br>=C2=A0 void call_foo_checked(=
T const&amp; v) {<br>=C2=A0=C2=A0=C2=A0 if (v) {<br>=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 v-&gt;foo();<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 }<br>=C2=A0 <br>=
=C2=A0 bar b;<br><br></span><span style=3D"font-family: courier new,monospa=
ce;">=C2=A0 call_foo_checked(std::make_unique&lt;bar&gt;(b));<br></span><sp=
an style=3D"font-family: courier new,monospace;">=C2=A0 call_foo_checked(st=
d::make_shared&lt;bar&gt;(b));<br></span><span style=3D"font-family: courie=
r new,monospace;">=C2=A0 call_foo_checked(std::make_optional(b));<br></span=
><span style=3D"font-family: courier new,monospace;">=C2=A0 call_foo_checke=
d(std::make_view(b)); // operator bool returns true; check will be optimize=
d away<br></span><span style=3D"font-family: courier new,monospace;">=C2=A0=
 call_foo_checked(std::make_optional_view(b));<br></span><br></div><blockqu=
ote 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>To require pointe=
r syntax I think defeats this and makes such proposals a moot point, since =
we could implement our own pretty trivilly where required - and indeed, oft=
en do. What operator dot et al propose is a way to save us that work by add=
ing required scaffolding to the language itself, whch makes it moot.<br></d=
iv></blockquote><div>=C2=A0<br>As I just explained, it&#39;s wrapper syntax=
, not just pointer syntax. And the idea is not necessarily to avoid specifi=
c syntax; it&#39;s to model a concept (in this case, views on objects) in a=
 natural way that meshes well with the rest of the language and standard li=
brary. I don&#39;t like the operator dot proposal because it does not feel =
natural; it feels forced. That said, my aim here is not to prevent the prop=
osal from being accepted; I&#39;m just trying to provide an alternative whe=
n it comes to modelling the reference/view concept.<br><br>And many feature=
s of the standard library could be trivially implemented; there are reasons=
 for including something in the standard library other than &quot;it&#39;s =
hard to implement&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/ef844f2c-8a17-44d0-b1e9-9c6ff2cdbda7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ef844f2c-8a17-44d0-b1e9-9c6ff2cdbda7=
%40isocpp.org</a>.<br />

------=_Part_2969_1973707989.1476168884379--

------=_Part_2968_1958495499.1476168884379--

.


Author: mihailnajdenov@gmail.com
Date: Tue, 11 Oct 2016 00:24:19 -0700 (PDT)
Raw View
------=_Part_881_75401625.1476170659294
Content-Type: multipart/alternative;
 boundary="----=_Part_882_542862724.1476170659294"

------=_Part_882_542862724.1476170659294
Content-Type: text/plain; charset=UTF-8

The ironic part is - operator.() is proposed exactly because *o = 42 (o
being optional) is cumbersome.
In the dot proposal there is even an example of implementing optional on
top of the dot op!

In any case dot op is "enabling technology" - its uses exceed using it to
implement references, it is just that this particular proposal focuses way
too much on references.
There are other proposals which focus on other uses.

--
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/01673d6d-0d1d-443c-9d7a-bfc487d3946c%40isocpp.org.

------=_Part_882_542862724.1476170659294
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>The ironic part is - operator.() is proposed exactly =
because *o =3D 42 (o being optional)=C2=A0is cumbersome. </div><div>In the =
dot proposal there is even an example of implementing optional on top of th=
e dot op! =C2=A0</div><div><br></div><div>In any case dot op is &quot;enabl=
ing technology&quot; - its uses exceed using it to implement references, it=
 is just that=C2=A0this particular proposal focuses way too much on referen=
ces. </div><div>There are other proposals which focus on other uses. </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/01673d6d-0d1d-443c-9d7a-bfc487d3946c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/01673d6d-0d1d-443c-9d7a-bfc487d3946c=
%40isocpp.org</a>.<br />

------=_Part_882_542862724.1476170659294--

------=_Part_881_75401625.1476170659294--

.


Author: joseph.thomson@gmail.com
Date: Tue, 11 Oct 2016 01:18:43 -0700 (PDT)
Raw View
------=_Part_727_1084286316.1476173923293
Content-Type: multipart/alternative;
 boundary="----=_Part_728_439565663.1476173923293"

------=_Part_728_439565663.1476173923293
Content-Type: text/plain; charset=UTF-8


On Tuesday, 11 October 2016 15:24:19 UTC+8, mihailn...@gmail.com wrote:
>
> The ironic part is - operator.() is proposed exactly because *o = 42 (o
> being optional) is cumbersome.
> In the dot proposal there is even an example of implementing optional on
> top of the dot op!
>

I realize that this is why the proposal exists, hence why I called it
"syntactic sugar". I don't see how all this added complexity is worth it
just to avoid typing one additional character.


>
> In any case dot op is "enabling technology" - its uses exceed using it to
> implement references, it is just that this particular proposal focuses way
> too much on references.
> There are other proposals which focus on other uses.
>
>
My proposal isn't specifically about operator dot, and I mentioned that the
proposals may be orthogonal. My proposal focuses on references because it
is about references (in the general sense, not the C++ syntactic sense).

--
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/593b2e80-9f04-430e-86c6-ea7537424d96%40isocpp.org.

------=_Part_728_439565663.1476173923293
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br>On Tuesday, 11 October 2016 15:24:19 UTC+8, mihailn...=
@gmail.com  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"><div>The ironic part is - operator.() is proposed exactly because *o =
=3D 42 (o being optional)=C2=A0is cumbersome. </div><div>In the dot proposa=
l there is even an example of implementing optional on top of the dot op! =
=C2=A0</div></div></blockquote><div><br>I realize that this is why the prop=
osal exists, hence why I called it &quot;syntactic sugar&quot;. I don&#39;t=
 see how all this added complexity is worth it just to avoid typing one add=
itional character.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><br></div><div>In any case dot op is &quot;enab=
ling technology&quot; - its uses exceed using it to implement references, i=
t is just that=C2=A0this particular proposal focuses way too much on refere=
nces. </div><div>There are other proposals which focus on other uses. </div=
><div><br></div></div></blockquote><div><br>My proposal isn&#39;t specifica=
lly about operator dot, and I mentioned that the proposals may be orthogona=
l. My proposal focuses on references because it is about references (in the=
 general sense, not the C++ syntactic sense).<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/593b2e80-9f04-430e-86c6-ea7537424d96%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/593b2e80-9f04-430e-86c6-ea7537424d96=
%40isocpp.org</a>.<br />

------=_Part_728_439565663.1476173923293--

------=_Part_727_1084286316.1476173923293--

.


Author: "D. B." <db0451@gmail.com>
Date: Tue, 11 Oct 2016 09:45:01 +0100
Raw View
--089e01227ed26d94fc053e92e4fa
Content-Type: text/plain; charset=UTF-8

But it's not. It's about handles with pointer syntax.

A smart reference would be something that could be used as-if it was the
referred object, but while applying other
checks/validation/proxying/younameit on top of it. It should be
substitutable into template code that expects normal references - and hence
never uses * or -> - without said code being any the wiser.

What you're proposing isn't a smart reference. It's an even dumber pointer.

--
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/CACGiwhHD4gvnXEXaAoSmjB9YbVF3Gg346Kq4CTvt-yHV2YMniA%40mail.gmail.com.

--089e01227ed26d94fc053e92e4fa
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><div>But it&#39;s not. It&#39;s about handles with po=
inter syntax.<br><br></div>A smart reference would be something that could =
be used as-if it was the referred object, but while applying other checks/v=
alidation/proxying/younameit on top of it. It should be substitutable into =
template code that expects normal references - and hence never uses * or -&=
gt; - without said code being any the wiser.<br><br></div>What you&#39;re p=
roposing isn&#39;t a smart reference. It&#39;s an even dumber pointer.<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/CACGiwhHD4gvnXEXaAoSmjB9YbVF3Gg346Kq4=
CTvt-yHV2YMniA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CACGiwhHD4gvnXEXa=
AoSmjB9YbVF3Gg346Kq4CTvt-yHV2YMniA%40mail.gmail.com</a>.<br />

--089e01227ed26d94fc053e92e4fa--

.


Author: "D. B." <db0451@gmail.com>
Date: Tue, 11 Oct 2016 09:48:17 +0100
Raw View
--089e013d167013a188053e92f035
Content-Type: text/plain; charset=UTF-8

On Tue, Oct 11, 2016 at 7:54 AM, <joseph.thomson@gmail.com> wrote:

> Conversely, the point of the recent smart reference proposals, AFAICT -
>> other than making writing code a lot easier in supportive situations - is
>> that they could be transparently incorporated into generic code that would
>> work with plain reference.
>>
>
>
> I'm not sure what you mean by "supportive situations". And I would like to
> see some real examples of where it is useful to be able to write generic
> code using reference syntax (operator dot). I'm not denying such examples
> exist, I just can't think of any myself. And it's possible to write generic
> code that operates on all wrapper types.
>


I meant "relevant situations". Such as those where I currently have to
write my own handle/proxy classes, which in 99% of cases just
reimplement/forward countless trivial operators/methods. With a transparent
smart reference, myself and other programmers in analogous situations - who
I don't think are as uncommon as you imply - would not need to do that. We
would only override the operations where we needed special behaviour, and
let operator.(), or equivalent, forward anything that we didn't explicitly
'overridde'.

--
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/CACGiwhGs3zp9h_omF8qgwAzx3%2B07DrUcikQE7O4NFJJ-ASerkA%40mail.gmail.com.

--089e013d167013a188053e92f035
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
ue, Oct 11, 2016 at 7:54 AM,  <span dir=3D"ltr">&lt;<a href=3D"mailto:josep=
h.thomson@gmail.com" target=3D"_blank">joseph.thomson@gmail.com</a>&gt;</sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=
=3D""></span><span class=3D""><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr">Conversely, the point of the recent smart reference proposals, =
AFAICT - other than making writing code a lot easier in supportive situatio=
ns - is that they could be transparently incorporated into generic code tha=
t would work with plain reference.</div></blockquote></span><br><span class=
=3D""></span><div><br>I&#39;m not sure what you mean by &quot;supportive si=
tuations&quot;. And I would like to see some real examples of where it is u=
seful to be able to write generic code using reference syntax (operator dot=
). I&#39;m not denying such examples exist, I just can&#39;t think of any m=
yself. And it&#39;s possible to write generic code that operates on all wra=
pper types.<br></div></div></blockquote><div><br><br></div><div>I meant &qu=
ot;relevant situations&quot;. Such as those where I currently have to write=
 my own handle/proxy classes, which in 99% of cases just reimplement/forwar=
d countless trivial operators/methods. With a transparent smart reference, =
myself and other programmers in analogous situations - who I don&#39;t thin=
k are as uncommon as you imply - would not need to do that. We would only o=
verride the operations where we needed special behaviour, and let operator.=
(), or equivalent, forward anything that we didn&#39;t explicitly &#39;over=
ridde&#39;.<br></div><div>=C2=A0<br></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/CACGiwhGs3zp9h_omF8qgwAzx3%2B07DrUcik=
QE7O4NFJJ-ASerkA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CACGiwhGs3zp9h_=
omF8qgwAzx3%2B07DrUcikQE7O4NFJJ-ASerkA%40mail.gmail.com</a>.<br />

--089e013d167013a188053e92f035--

.


Author: joseph.thomson@gmail.com
Date: Tue, 11 Oct 2016 02:17:46 -0700 (PDT)
Raw View
------=_Part_2829_205539926.1476177467025
Content-Type: multipart/alternative;
 boundary="----=_Part_2830_1565519314.1476177467025"

------=_Part_2830_1565519314.1476177467025
Content-Type: text/plain; charset=UTF-8



> But it's not. It's about handles with pointer syntax.
>

I'm trying to draw a distinction between C++ references and references as a
general concept. References indirectly refer to objects. Both C++ pointers
and C++ references are forms of reference in the general sense. My proposed
types are handles that override operator* and operator->, so they are
handles with pointer syntax much like std::optional is a handle with
pointer syntax.

A smart reference would be something that could be used as-if it was the
> referred object, but while applying other
> checks/validation/proxying/younameit on top of it. It should be
> substitutable into template code that expects normal references - and hence
> never uses * or -> - without said code being any the wiser.
>

Okay, then I don't claim that what I'm proposing are smart references. What
I'm proposing are views, as per my chosen type names, which are a kind of
reference type in the general sense.


> What you're proposing isn't a smart reference. It's an even dumber pointer.
>

It's not a pointer because it doesn't have pointer semantics. But it is
just about as dumb as std::observer_ptr, hence why I drew the comparison. I
wouldn't say it's any dumber though.

I meant "relevant situations". Such as those where I currently have to
> write my own handle/proxy classes, which in 99% of cases just
> reimplement/forward countless trivial operators/methods. With a transparent
> smart reference, myself and other programmers in analogous situations - who
> I don't think are as uncommon as you imply - would not need to do that. We
> would only override the operations where we needed special behaviour, and
> let operator.(), or equivalent, forward anything that we didn't explicitly
> 'overridde'.
>

Yes, this is the compile-time overriding that I mentioned in the opening
paragraph of my first post. This is not the problem I am trying to solve.
As I said, I am not trying to prevent the operator dot proposal being
accepted, even though I don't like it very much. I am just presenting an
alternative solution for one particular use case of operator dot
overloading.

--
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/51343022-120f-40a7-bb01-92ee19e7a01e%40isocpp.org.

------=_Part_2830_1565519314.1476177467025
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px =
0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class=
=3D"gmail_quote"><div><div>But it&#39;s not. It&#39;s about handles with po=
inter syntax.<br></div></div></blockquote><div><br>I&#39;m trying to draw a=
 distinction between C++ references and references as a general concept. Re=
ferences indirectly refer to objects. Both C++ pointers and C++ references =
are forms of reference in the general sense. My proposed types are handles =
that override <span style=3D"font-family: courier new,monospace;">operator*=
</span> and <span style=3D"font-family: courier new,monospace;">operator-&g=
t;</span>, so they are handles with pointer syntax much like <span style=3D=
"font-family: courier new,monospace;">std::optional</span> is a handle with=
 pointer syntax. <br><br></div><blockquote style=3D"margin: 0px 0px 0px 0.8=
ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class=3D=
"gmail_quote"><div>A
 smart reference would be something that could be used as-if it was the=20
referred object, but while applying other checks/validation/proxying/<wbr>y=
ounameit
 on top of it. It should be substitutable into template code that=20
expects normal references - and hence never uses * or -&gt; - without=20
said code being any the wiser.<br></div></blockquote><div><br>Okay, then I =
don&#39;t claim that what I&#39;m proposing are smart references. What I&#3=
9;m proposing are views, as per my chosen type names, which are a kind of r=
eference type in the general sense.<br>=C2=A0</div><blockquote style=3D"mar=
gin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-=
left: 1ex;" class=3D"gmail_quote"><div></div>What you&#39;re proposing isn&=
#39;t a smart reference. It&#39;s an even dumber pointer.<br></blockquote><=
br>It&#39;s not a pointer because it doesn&#39;t have pointer semantics. Bu=
t it is just about as dumb as <span style=3D"font-family: courier new,monos=
pace;">std::observer_ptr</span>, hence why I drew the comparison. I wouldn&=
#39;t say it&#39;s any dumber though.<br><br><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote">I meant &qu=
ot;relevant situations&quot;. Such as those where I currently have to write=
 my own handle/proxy classes, which in 99% of cases just reimplement/forwar=
d countless trivial operators/methods. With a transparent smart reference, =
myself and other programmers in analogous situations - who I don&#39;t thin=
k are as uncommon as you imply - would not need to do that. We would only o=
verride the operations where we needed special behaviour, and let operator.=
(), or equivalent, forward anything that we didn&#39;t explicitly &#39;over=
ridde&#39;.<br></div></div></div></blockquote><div><br>Yes, this is the com=
pile-time overriding that I mentioned in the opening paragraph of my first =
post. This is not the problem I am trying to solve. As I said, I am not try=
ing to prevent the operator dot proposal being accepted, even though I don&=
#39;t like it very much. I am just presenting an alternative solution for o=
ne particular use case of operator dot overloading.<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/51343022-120f-40a7-bb01-92ee19e7a01e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/51343022-120f-40a7-bb01-92ee19e7a01e=
%40isocpp.org</a>.<br />

------=_Part_2830_1565519314.1476177467025--

------=_Part_2829_205539926.1476177467025--

.


Author: "D. B." <db0451@gmail.com>
Date: Tue, 11 Oct 2016 10:24:33 +0100
Raw View
--089e01228c12c9856d053e93710a
Content-Type: text/plain; charset=UTF-8

Cool, I guess I focused in too much on the comparison to operator dot and
mistakenly inferred this was intended as a direct rival for that, rather
than a complimentary alternative. In that case, carry on - and I'll reread
it all properly now. :)

--
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/CACGiwhGzGGZSo2A-ni1H9xRvjsgR5CmYdBKq8ZE8ftO4J7ZsaA%40mail.gmail.com.

--089e01228c12c9856d053e93710a
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Cool, I guess I focused in too much on the comparison to o=
perator dot and mistakenly inferred this was intended as a direct rival for=
 that, rather than a complimentary alternative. In that case, carry on - an=
d I&#39;ll reread it all properly now. :)<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/CACGiwhGzGGZSo2A-ni1H9xRvjsgR5CmYdBKq=
8ZE8ftO4J7ZsaA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CACGiwhGzGGZSo2A-=
ni1H9xRvjsgR5CmYdBKq8ZE8ftO4J7ZsaA%40mail.gmail.com</a>.<br />

--089e01228c12c9856d053e93710a--

.


Author: joseph.thomson@gmail.com
Date: Tue, 11 Oct 2016 02:46:45 -0700 (PDT)
Raw View
------=_Part_3456_55641569.1476179205110
Content-Type: multipart/alternative;
 boundary="----=_Part_3457_1582750238.1476179205110"

------=_Part_3457_1582750238.1476179205110
Content-Type: text/plain; charset=UTF-8

Sorry. It's my fault! My intention was to show that operator dot wasn't a
necessary part of the solution to this problem, but I ended up focusing on
it too much.

On Tuesday, 11 October 2016 17:24:35 UTC+8, D. B. wrote:
>
> Cool, I guess I focused in too much on the comparison to operator dot and
> mistakenly inferred this was intended as a direct rival for that, rather
> than a complimentary alternative. In that case, carry on - and I'll reread
> it all properly now. :)
>
>

--
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/43b87b7e-d623-418d-b1ff-6d20ed5fae92%40isocpp.org.

------=_Part_3457_1582750238.1476179205110
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Sorry. It&#39;s my fault! My intention was to show that op=
erator dot wasn&#39;t a necessary part of the solution to this problem, but=
 I ended up focusing on it too much.<br><br>On Tuesday, 11 October 2016 17:=
24:35 UTC+8, D. B.  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">Cool, I guess I focused in too much on the comparison to opera=
tor dot and mistakenly inferred this was intended as a direct rival for tha=
t, rather than a complimentary alternative. In that case, carry on - and I&=
#39;ll reread it all properly now. :)<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/43b87b7e-d623-418d-b1ff-6d20ed5fae92%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/43b87b7e-d623-418d-b1ff-6d20ed5fae92=
%40isocpp.org</a>.<br />

------=_Part_3457_1582750238.1476179205110--

------=_Part_3456_55641569.1476179205110--

.


Author: mihailnajdenov@gmail.com
Date: Tue, 11 Oct 2016 04:46:37 -0700 (PDT)
Raw View
------=_Part_1067_1719553105.1476186398060
Content-Type: multipart/alternative;
 boundary="----=_Part_1068_808712522.1476186398060"

------=_Part_1068_808712522.1476186398060
Content-Type: text/plain; charset=UTF-8

The problem is, it's kind of too late, because there is very strong
determination to get some (sort of) dot overloading into the standard.
It will not only enable smart refs/views, but other scenarios as well.

--
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/46c4022e-720c-45fb-823d-751c6d8af365%40isocpp.org.

------=_Part_1068_808712522.1476186398060
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>The problem is, it&#39;s kind of too late, because th=
ere is very strong determination to get some (sort of) dot overloading into=
 the standard. </div><div>It will not only enable smart refs/views, but oth=
er scenarios as well.=C2=A0=C2=A0</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/46c4022e-720c-45fb-823d-751c6d8af365%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/46c4022e-720c-45fb-823d-751c6d8af365=
%40isocpp.org</a>.<br />

------=_Part_1068_808712522.1476186398060--

------=_Part_1067_1719553105.1476186398060--

.


Author: joseph.thomson@gmail.com
Date: Tue, 11 Oct 2016 17:03:20 -0700 (PDT)
Raw View
------=_Part_2926_25365031.1476230601007
Content-Type: multipart/alternative;
 boundary="----=_Part_2927_542019418.1476230601007"

------=_Part_2927_542019418.1476230601007
Content-Type: text/plain; charset=UTF-8

As I said, I am not making a case against operator dot overloading. My
mistake was conflating C++ references and references in the general sense
(what I am calling "views"). Smart references are types that mimic C++
references. "Views" are types that model non-owning references in the
general sense. I believe this proposal is orthogonal to any operator dot
overloading proposal, as not all "references" have to look like C++
references.

On Tuesday, 11 October 2016 19:46:38 UTC+8, mihailn...@gmail.com wrote:
>
> The problem is, it's kind of too late, because there is very strong
> determination to get some (sort of) dot overloading into the standard.
> It will not only enable smart refs/views, but other scenarios as well.
>

--
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/e81406c7-a398-4851-97b2-638d74312e66%40isocpp.org.

------=_Part_2927_542019418.1476230601007
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">As I said, I am not making a case against operator dot ove=
rloading. My mistake was conflating C++ references and references in the ge=
neral sense (what I am calling &quot;views&quot;). Smart references are typ=
es that mimic C++ references. &quot;Views&quot; are types that model non-ow=
ning references in the general sense. I believe this proposal is orthogonal=
 to any operator dot overloading proposal, as not all &quot;references&quot=
; have to look like C++ references.<br><br>On Tuesday, 11 October 2016 19:4=
6:38 UTC+8, mihailn...@gmail.com  wrote:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div>The problem is, it&#39;s kind of too late, =
because there is very strong determination to get some (sort of) dot overlo=
ading into the standard. </div><div>It will not only enable smart refs/view=
s, but other scenarios as well.=C2=A0=C2=A0</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/e81406c7-a398-4851-97b2-638d74312e66%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e81406c7-a398-4851-97b2-638d74312e66=
%40isocpp.org</a>.<br />

------=_Part_2927_542019418.1476230601007--

------=_Part_2926_25365031.1476230601007--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 11 Oct 2016 17:19:53 -0700 (PDT)
Raw View
------=_Part_900_1076726099.1476231593514
Content-Type: multipart/alternative;
 boundary="----=_Part_901_405721596.1476231593514"

------=_Part_901_405721596.1476231593514
Content-Type: text/plain; charset=UTF-8

On Tuesday, October 11, 2016 at 8:03:21 PM UTC-4, joseph....@gmail.com
wrote:
>
> As I said, I am not making a case against operator dot overloading. My
> mistake was conflating C++ references and references in the general sense
> (what I am calling "views"). Smart references are types that mimic C++
> references. "Views" are types that model non-owning references in the
> general sense. I believe this proposal is orthogonal to any operator dot
> overloading proposal, as not all "references" have to look like C++
> references.
>

I just don't see the point of a generalized `view` and your `optional_view`.

`view<T>` is just `not_null<T*>`; `optional_view<T>` is just `T*`. If you
don't like the pointer semantics of it... tough.

--
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/8ebe632f-9293-421e-ad10-5e0c5c485ccd%40isocpp.org.

------=_Part_901_405721596.1476231593514
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, October 11, 2016 at 8:03:21 PM UTC-4, joseph..=
...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr">As I said, I am not making a case against operator dot overloading. M=
y mistake was conflating C++ references and references in the general sense=
 (what I am calling &quot;views&quot;). Smart references are types that mim=
ic C++ references. &quot;Views&quot; are types that model non-owning refere=
nces in the general sense. I believe this proposal is orthogonal to any ope=
rator dot overloading proposal, as not all &quot;references&quot; have to l=
ook like C++ references.</div></blockquote><div><br>I just don&#39;t see th=
e point of a generalized `view` and your `optional_view`.<br><br>`view&lt;T=
&gt;` is just `not_null&lt;T*&gt;`; `optional_view&lt;T&gt;` is just `T*`. =
If you don&#39;t like the pointer semantics of it... tough.<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/8ebe632f-9293-421e-ad10-5e0c5c485ccd%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8ebe632f-9293-421e-ad10-5e0c5c485ccd=
%40isocpp.org</a>.<br />

------=_Part_901_405721596.1476231593514--

------=_Part_900_1076726099.1476231593514--

.


Author: joseph.thomson@gmail.com
Date: Tue, 11 Oct 2016 18:09:20 -0700 (PDT)
Raw View
------=_Part_8080_1881260250.1476234560393
Content-Type: multipart/alternative;
 boundary="----=_Part_8081_1630832672.1476234560393"

------=_Part_8081_1630832672.1476234560393
Content-Type: text/plain; charset=UTF-8

I don't like the pointer semantics of not_null. Unnatural semantics hint at
incorrect design. not_null is great for making existing and legacy code
safer, but it is not the ideal design for a "view" type.

One of the main differences between not_null and view is that not_null
detects null pointer errors at run time, while view catches them at compile
time.

  void foo(int* p) {
    not_null<int*> nn = p; // run-time exception
    view<int> = p; // compile-time error
  }

On Wednesday, 12 October 2016 08:19:53 UTC+8, Nicol Bolas wrote:
>
> On Tuesday, October 11, 2016 at 8:03:21 PM UTC-4, joseph....@gmail.com
> wrote:
>>
>> As I said, I am not making a case against operator dot overloading. My
>> mistake was conflating C++ references and references in the general sense
>> (what I am calling "views"). Smart references are types that mimic C++
>> references. "Views" are types that model non-owning references in the
>> general sense. I believe this proposal is orthogonal to any operator dot
>> overloading proposal, as not all "references" have to look like C++
>> references.
>>
>
> I just don't see the point of a generalized `view` and your
> `optional_view`.
>
> `view<T>` is just `not_null<T*>`; `optional_view<T>` is just `T*`. If you
> don't like the pointer semantics of it... tough.
>

--
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/2ee3050d-ee55-42ed-b1ee-16503ea5296b%40isocpp.org.

------=_Part_8081_1630832672.1476234560393
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I don&#39;t like the pointer semantics of <span style=3D"f=
ont-family: courier new,monospace;">not_null</span>. Unnatural semantics hi=
nt at incorrect design. <span style=3D"font-family: courier new,monospace;"=
>not_null</span>
 is great for making existing and legacy code safer, but it is not the=20
ideal design for a &quot;view&quot; type.<br><br>One of the main difference=
s between=20
<span style=3D"font-family: courier new,monospace;">not_null</span> and <sp=
an style=3D"font-family: courier new,monospace;">view</span> is that <span =
style=3D"font-family: courier new,monospace;">not_null</span> detects null =
pointer errors at run time,=20
while <span style=3D"font-family: courier new,monospace;">view</span> catch=
es them at compile time.<br><br><span style=3D"font-family: courier new,mon=
ospace;">=C2=A0 void foo(int* p) {<br>=C2=A0 =C2=A0 not_null&lt;int*&gt; nn=
 =3D p; // run-time exception<br>=C2=A0=C2=A0=C2=A0 view&lt;int&gt; =3D p; =
// compile-time error<br>=C2=A0 }</span><br><br>On Wednesday, 12 October 20=
16 08:19:53 UTC+8, Nicol Bolas  wrote:<blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr">On Tuesday, October 11, 2016 at 8:03:21 PM UTC-4, =
<a>joseph....@gmail.com</a> 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">As I said, I am not making a case against operator dot ov=
erloading. My mistake was conflating C++ references and references in the g=
eneral sense (what I am calling &quot;views&quot;). Smart references are ty=
pes that mimic C++ references. &quot;Views&quot; are types that model non-o=
wning references in the general sense. I believe this proposal is orthogona=
l to any operator dot overloading proposal, as not all &quot;references&quo=
t; have to look like C++ references.</div></blockquote><div><br>I just don&=
#39;t see the point of a generalized `view` and your `optional_view`.<br><b=
r>`view&lt;T&gt;` is just `not_null&lt;T*&gt;`; `optional_view&lt;T&gt;` is=
 just `T*`. If you don&#39;t like the pointer semantics of it... tough.<br>=
</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/2ee3050d-ee55-42ed-b1ee-16503ea5296b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2ee3050d-ee55-42ed-b1ee-16503ea5296b=
%40isocpp.org</a>.<br />

------=_Part_8081_1630832672.1476234560393--

------=_Part_8080_1881260250.1476234560393--

.


Author: joseph.thomson@gmail.com
Date: Tue, 11 Oct 2016 18:24:06 -0700 (PDT)
Raw View
------=_Part_7234_29638966.1476235446644
Content-Type: multipart/alternative;
 boundary="----=_Part_7235_1970698885.1476235446644"

------=_Part_7235_1970698885.1476235446644
Content-Type: text/plain; charset=UTF-8

And yes, I know that the potential error of an assignment of int* to
not_null<int*> can be caught by a static analysis tool, but A) this
requires a static analysis tool, and B) not_null and view are
complementary. Let me rewrite my example:

  void foo(not_null<int*> p) { // legacy interface made safer with not_null
    view<int> v = *p; // modern implementation (static analysis: a-okay)
    ...
  }

On Wednesday, 12 October 2016 09:09:20 UTC+8, joseph....@gmail.com wrote:
>
> I don't like the pointer semantics of not_null. Unnatural semantics hint
> at incorrect design. not_null is great for making existing and legacy
> code safer, but it is not the ideal design for a "view" type.
>
> One of the main differences between not_null and view is that not_null
> detects null pointer errors at run time, while view catches them at
> compile time.
>
>   void foo(int* p) {
>     not_null<int*> nn = p; // run-time exception
>     view<int> = p; // compile-time error
>   }
>

--
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/041b8772-4d46-4faa-bc06-d6da741b620d%40isocpp.org.

------=_Part_7235_1970698885.1476235446644
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">And yes, I know that the potential error of an assignment =
of <span style=3D"font-family: courier new,monospace;">int*</span> to <span=
 style=3D"font-family: courier new,monospace;">not_null&lt;int*&gt;</span> =
can be caught by a static analysis tool, but A) this requires a static anal=
ysis tool, and B) <span style=3D"font-family: courier new,monospace;">not_n=
ull</span> and <span style=3D"font-family: courier new,monospace;">view</sp=
an> are complementary. Let me rewrite my example:<br><br><span style=3D"fon=
t-family:courier new,monospace">=C2=A0 void foo(not_null&lt;int*&gt; p) { /=
/ legacy interface made safer with not_null<br>=C2=A0=C2=A0=C2=A0 view&lt;i=
nt&gt; v =3D *p; // modern implementation (static analysis: a-okay)<br>=C2=
=A0=C2=A0=C2=A0 ...<br>=C2=A0 }</span><br><br>On Wednesday, 12 October 2016=
 09:09:20 UTC+8, joseph....@gmail.com  wrote:<blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr">I don&#39;t like the pointer semantics of <=
span style=3D"font-family:courier new,monospace">not_null</span>. Unnatural=
 semantics hint at incorrect design. <span style=3D"font-family:courier new=
,monospace">not_null</span>
 is great for making existing and legacy code safer, but it is not the=20
ideal design for a &quot;view&quot; type.<br><br>One of the main difference=
s between=20
<span style=3D"font-family:courier new,monospace">not_null</span> and <span=
 style=3D"font-family:courier new,monospace">view</span> is that <span styl=
e=3D"font-family:courier new,monospace">not_null</span> detects null pointe=
r errors at run time,=20
while <span style=3D"font-family:courier new,monospace">view</span> catches=
 them at compile time.<br><br><span style=3D"font-family:courier new,monosp=
ace">=C2=A0 void foo(int* p) {<br>=C2=A0 =C2=A0 not_null&lt;int*&gt; nn =3D=
 p; // run-time exception<br>=C2=A0=C2=A0=C2=A0 view&lt;int&gt; =3D p; // c=
ompile-time error<br>=C2=A0 }</span><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/041b8772-4d46-4faa-bc06-d6da741b620d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/041b8772-4d46-4faa-bc06-d6da741b620d=
%40isocpp.org</a>.<br />

------=_Part_7235_1970698885.1476235446644--

------=_Part_7234_29638966.1476235446644--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 11 Oct 2016 19:06:11 -0700 (PDT)
Raw View
------=_Part_3995_723241646.1476237971797
Content-Type: multipart/alternative;
 boundary="----=_Part_3996_1651651270.1476237971798"

------=_Part_3996_1651651270.1476237971798
Content-Type: text/plain; charset=UTF-8

On Tuesday, October 11, 2016 at 9:24:06 PM UTC-4, joseph....@gmail.com
wrote:
>
> On Wednesday, 12 October 2016 09:09:20 UTC+8, joseph....@gmail.com wrote:
>>
>> I don't like the pointer semantics of not_null. Unnatural semantics hint
>> at incorrect design. not_null is great for making existing and legacy
>> code safer, but it is not the ideal design for a "view" type.
>>
>> One of the main differences between not_null and view is that not_null
>> detects null pointer errors at run time, while view catches them at
>> compile time.
>>
>>   void foo(int* p) {
>>     not_null<int*> nn = p; // run-time exception
>>     view<int> = p; // compile-time error
>>   }
>>
>
That's not a NULL pointer check. Nothing ever detects that `p` is a null
pointer. It fails to compile only because `view<int>` cannot be constructed
from a pointer at all. If you had done `view<int> = *p`, it would compile
just fine. What it would not do is actually catch an error if you pass
`nullptr` to `foo`. It would simply invoke UB.

And yes, I know that the potential error of an assignment of int* to
> not_null<int*> can be caught by a static analysis tool, but A) this
> requires a static analysis tool, and B) not_null and view are
> complementary. Let me rewrite my example:
>
>   void foo(not_null<int*> p) { // legacy interface made safer with not_null
>     view<int> v = *p; // modern implementation (static analysis: a-okay)
>     ...
>   }
>

But why would you use `view<int>` inside of `foo` at all? There would be no
objective *need*, unless you're just allergic to using `->`.

--
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/142ffa44-8b33-49a6-888a-0a1a78ae6a83%40isocpp.org.

------=_Part_3996_1651651270.1476237971798
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, October 11, 2016 at 9:24:06 PM UTC-4, joseph..=
...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr">On Wednesday, 12 October 2016 09:09:20 UTC+8, <a>joseph....@gmail.com=
</a>  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">I don&=
#39;t like the pointer semantics of <span style=3D"font-family:courier new,=
monospace">not_null</span>. Unnatural semantics hint at incorrect design. <=
span style=3D"font-family:courier new,monospace">not_null</span>
 is great for making existing and legacy code safer, but it is not the=20
ideal design for a &quot;view&quot; type.<br><br>One of the main difference=
s between=20
<span style=3D"font-family:courier new,monospace">not_null</span> and <span=
 style=3D"font-family:courier new,monospace">view</span> is that <span styl=
e=3D"font-family:courier new,monospace">not_null</span> detects null pointe=
r errors at run time,=20
while <span style=3D"font-family:courier new,monospace">view</span> catches=
 them at compile time.<br><br><span style=3D"font-family:courier new,monosp=
ace">=C2=A0 void foo(int* p) {<br>=C2=A0 =C2=A0 not_null&lt;int*&gt; nn =3D=
 p; // run-time exception<br>=C2=A0=C2=A0=C2=A0 view&lt;int&gt; =3D p; // c=
ompile-time error<br>=C2=A0 }</span></div></blockquote></div></blockquote><=
div><br>That&#39;s not a NULL pointer check. Nothing ever detects that `p` =
is a null
 pointer. It fails to compile only because `view&lt;int&gt;` cannot be=20
constructed from a pointer at all. If you had done `view&lt;int&gt; =3D=20
*p`, it would compile just fine. What it would not do is actually catch=20
an error if you pass `nullptr` to `foo`. It would simply invoke UB. <br><br=
><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; bord=
er-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">And yes, I know =
that the potential error of an assignment of <span style=3D"font-family:cou=
rier new,monospace">int*</span> to <span style=3D"font-family:courier new,m=
onospace">not_null&lt;int*&gt;</span> can be caught by a static analysis to=
ol, but A) this requires a static analysis tool, and B) <span style=3D"font=
-family:courier new,monospace">not_null</span> and <span style=3D"font-fami=
ly:courier new,monospace">view</span> are complementary. Let me rewrite my =
example:<br><br><span style=3D"font-family:courier new,monospace">=C2=A0 vo=
id foo(not_null&lt;int*&gt; p) { // legacy interface made safer with not_nu=
ll</span><br><span style=3D"font-family:courier new,monospace">=C2=A0=C2=A0=
=C2=A0 view&lt;int&gt; v =3D *p; // modern implementation (static analysis:=
 a-okay)</span><br><span style=3D"font-family:courier new,monospace">=C2=A0=
=C2=A0=C2=A0 ...</span><br><span style=3D"font-family:courier new,monospace=
">=C2=A0 }</span><br></blockquote><br>But why would you use `view&lt;int&gt=
;` inside of `foo` at all? There would be no objective <i>need</i>, unless =
you&#39;re just allergic to using `-&gt;`.<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/142ffa44-8b33-49a6-888a-0a1a78ae6a83%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/142ffa44-8b33-49a6-888a-0a1a78ae6a83=
%40isocpp.org</a>.<br />

------=_Part_3996_1651651270.1476237971798--

------=_Part_3995_723241646.1476237971797--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 11 Oct 2016 19:08:15 -0700 (PDT)
Raw View
------=_Part_2023_158793688.1476238095176
Content-Type: multipart/alternative;
 boundary="----=_Part_2024_78005852.1476238095177"

------=_Part_2024_78005852.1476238095177
Content-Type: text/plain; charset=UTF-8



On Tuesday, October 11, 2016 at 10:06:12 PM UTC-4, Nicol Bolas wrote:
>
> On Tuesday, October 11, 2016 at 9:24:06 PM UTC-4, joseph....@gmail.com
> wrote:
>
>> And yes, I know that the potential error of an assignment of int* to
>> not_null<int*> can be caught by a static analysis tool, but A) this
>> requires a static analysis tool, and B) not_null and view are
>> complementary. Let me rewrite my example:
>>
>>   void foo(not_null<int*> p) { // legacy interface made safer with
>> not_null
>>     view<int> v = *p; // modern implementation (static analysis: a-okay)
>>     ...
>>   }
>>
>
> But why would you use `view<int>` inside of `foo` at all? There would be
> no objective *need*, unless you're just allergic to using `->`.
>

Let me rephrase that bit at the end.

`view<int>` and `not_null<int*>` have almost exactly the same interface.
The *only difference* between them is that one takes references and the
other takes pointers.

That trivial difference is not worth creating a whole new type for.

--
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/15f04dae-8f9c-468a-a2ab-800ce1305e24%40isocpp.org.

------=_Part_2024_78005852.1476238095177
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Tuesday, October 11, 2016 at 10:06:12 PM UTC-4,=
 Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr">On Tuesday, October 11, 2016 at 9:24:06 PM UTC-4, <a>joseph....@gmail=
..com</a> wrote:<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">A=
nd yes, I know that the potential error of an assignment of <span style=3D"=
font-family:courier new,monospace">int*</span> to <span style=3D"font-famil=
y:courier new,monospace">not_null&lt;int*&gt;</span> can be caught by a sta=
tic analysis tool, but A) this requires a static analysis tool, and B) <spa=
n style=3D"font-family:courier new,monospace">not_null</span> and <span sty=
le=3D"font-family:courier new,monospace">view</span> are complementary. Let=
 me rewrite my example:<br><br><span style=3D"font-family:courier new,monos=
pace">=C2=A0 void foo(not_null&lt;int*&gt; p) { // legacy interface made sa=
fer with not_null</span><br><span style=3D"font-family:courier new,monospac=
e">=C2=A0=C2=A0=C2=A0 view&lt;int&gt; v =3D *p; // modern implementation (s=
tatic analysis: a-okay)</span><br><span style=3D"font-family:courier new,mo=
nospace">=C2=A0=C2=A0=C2=A0 ...</span><br><span style=3D"font-family:courie=
r new,monospace">=C2=A0 }</span><br></blockquote><br>But why would you use =
`view&lt;int&gt;` inside of `foo` at all? There would be no objective <i>ne=
ed</i>, unless you&#39;re just allergic to using `-&gt;`.<br></div></div></=
blockquote><div><br>Let me rephrase that bit at the end.<br><br>`view&lt;in=
t&gt;` and `not_null&lt;int*&gt;` have almost exactly the same interface. T=
he <i>only difference</i> between them is that one takes references and the=
 other takes pointers.<br><br>That trivial difference is not worth creating=
 a whole new type for. <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/15f04dae-8f9c-468a-a2ab-800ce1305e24%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/15f04dae-8f9c-468a-a2ab-800ce1305e24=
%40isocpp.org</a>.<br />

------=_Part_2024_78005852.1476238095177--

------=_Part_2023_158793688.1476238095176--

.


Author: joseph.thomson@gmail.com
Date: Tue, 11 Oct 2016 20:54:27 -0700 (PDT)
Raw View
------=_Part_7415_1088349909.1476244467536
Content-Type: multipart/alternative;
 boundary="----=_Part_7416_991757972.1476244467537"

------=_Part_7416_991757972.1476244467537
Content-Type: text/plain; charset=UTF-8


  void foo(not_null<int*> p) { // legacy interface made safer with not_null

>     view<int> v = *p; // modern implementation (static analysis: a-okay)
>>>     ...
>>>   }
>>>
>>
>> But why would you use `view<int>` inside of `foo` at all? There would be
>> no objective *need*, unless you're just allergic to using `->`.
>>
>
It's just a contrived example. I will try to give more practical examples
from now on (and I assume given your follow-up, you noticed that view does
require operator->).

One of the main differences between not_null and view is that not_null
>>> detects null pointer errors at run time, while view catches them at
>>> compile time.
>>>
>>>   void foo(int* p) {
>>>     not_null<int*> nn = p; // run-time exception
>>>     view<int> = p; // compile-time error
>>>   }
>>>
>>
> That's not a NULL pointer check. Nothing ever detects that `p` is a null
> pointer. It fails to compile only because `view<int>` cannot be constructed
> from a pointer at all. If you had done `view<int> = *p`, it would compile
> just fine. What it would not do is actually catch an error if you pass
> `nullptr` to `foo`. It would simply invoke UB.
>

This was part of the motivation for my second example. Correct usage would
be something like this (disclaimer: the example is still somewhat
contrived). Given some class, watcher:

  class watcher {
    std::vector<view<item const>> watched_items;
    ...
  };

We might implement the method, watch:

  void watch(item const* i) {
    if (i) {
      watched_items.push_back(*i);
    } else {
      throw std::runtime_error("i cannot be null");
    }
  }

Or of course, we can use not_null to push the exception further up the call
stack:

  void watch(not_null<item const*> i) {
    watched_items.push_back(*i);
  }

Or, if we can modify the interface, we can make the caller responsible for
dereferencing their pointer:

  void watch(item const& i) {
    watched_items.push_back(i);
  }

Or maybe even:

  void foo(view<item const> i) {
    watched_items.push_back(i);
  }

A note about the last two examples: syntactically they are identical, but
semantically they are not. Use of view implies that the "reference" may be
stored by the class; use of reference to const is often done just for
performance reasons (to avoid making an expensive copy).

Let me rephrase that bit at the end.
>
> `view<int>` and `not_null<int*>` have almost exactly the same interface.
> The *only difference* between them is that one takes references and the
> other takes pointers.
>
> That trivial difference is not worth creating a whole new type for.
>

As I hope I've demonstrated, taking a pointer makes run time errors into
compile time errors and pushes those errors up the call stack. I think this
is important. I've already listed one other reason: semantics. view can
convey meaning. As for other features, it really is just general syntactic
niceness. The design of view and optional_view are still somewhat in flux,
but I can think of at least one other important feature.

I currently have it so that view<T> is implicitly convertible to T&. This
allows you to do things like this:

  void monitor_items() {
    for (item const& i : watched_items) {
      monitor(i);
    }
  }

This could be generic code that operates on both containers of T and
containers of view<T>. Another (contrived) example of this feature in use:

  std::array<int, 3> i = { 0, 1, 2 };
  std::map<std::string, optional_view<int>> m;

  m["a"] = i[0];
  m["b"] = i[1];
  m["c"] = i[2];

  int& b = m["b"];

Here I used optional_view because it is default constructible. I could have
used view if I had used map::emplace and map::at.

Note however that view<T> is not convertible to T. This is because I want
symmetry and consistency. view is not a value type, so I do not want it to
be able to implicitly convert to and from other value types. You have to
"dereference" it to access the underlying value. optional_view<T> also
implicitly converts to T&, but throws an exception if it is empty.

--
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/dd418983-c40b-4deb-8cff-e004547cc75a%40isocpp.org.

------=_Part_7416_991757972.1476244467537
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><span style=3D"font-family:courier new,monospace">=C2=
=A0 void foo(not_null&lt;int*&gt; p) { // legacy interface made safer with =
not_null</span><br><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><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"><span style=3D"font-family:couri=
er new,monospace">=C2=A0=C2=A0=C2=A0 view&lt;int&gt; v =3D *p; // modern im=
plementation (static analysis: a-okay)</span><br><span style=3D"font-family=
:courier new,monospace">=C2=A0=C2=A0=C2=A0 ...</span><br><span style=3D"fon=
t-family:courier new,monospace">=C2=A0 }</span><br></blockquote><br>But why=
 would you use `view&lt;int&gt;` inside of `foo` at all? There would be no =
objective <i>need</i>, unless you&#39;re just allergic to using `-&gt;`.<br=
></div></div></blockquote></div></blockquote><div><br>It&#39;s just a contr=
ived example. I will try to give more practical examples from now on (and I=
 assume given your follow-up, you noticed that view does require <span styl=
e=3D"font-family: courier new,monospace;">operator-&gt;</span>).<br><br></d=
iv><blockquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid r=
gb(204, 204, 204); padding-left: 1ex;" class=3D"gmail_quote"><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr">One of the main differences between=20
<span style=3D"font-family:courier new,monospace">not_null</span> and <span=
 style=3D"font-family:courier new,monospace">view</span> is that <span styl=
e=3D"font-family:courier new,monospace">not_null</span> detects null pointe=
r errors at run time,=20
while <span style=3D"font-family:courier new,monospace">view</span> catches=
 them at compile time.<br><br><span style=3D"font-family:courier new,monosp=
ace">=C2=A0 void foo(int* p) {<br>=C2=A0 =C2=A0 not_null&lt;int*&gt; nn =3D=
 p; // run-time exception<br>=C2=A0=C2=A0=C2=A0 view&lt;int&gt; =3D p; // c=
ompile-time error<br>=C2=A0 }</span></div></blockquote></div></blockquote><=
br>That&#39;s not a NULL pointer check. Nothing ever detects that `p` is a =
null
 pointer. It fails to compile only because `view&lt;int&gt;` cannot be=20
constructed from a pointer at all. If you had done `view&lt;int&gt; =3D=20
*p`, it would compile just fine. What it would not do is actually catch=20
an error if you pass `nullptr` to `foo`. It would simply invoke UB. <br></b=
lockquote><div><br>This was part of the motivation for my second example. C=
orrect usage would be something like this (disclaimer: the example is still=
 somewhat contrived). Given some class, <span style=3D"font-family: courier=
 new,monospace;">watcher</span>:<br><br><span style=3D"font-family:courier =
new,monospace">=C2=A0 class watcher {<br>=C2=A0 =C2=A0 std::vector&lt;view&=
lt;item const&gt;&gt; watched_items;<br>=C2=A0=C2=A0=C2=A0 ...<br>=C2=A0 };=
<br><span style=3D"font-family: arial,sans-serif;"><br>We might implement t=
he method, <span style=3D"font-family: courier new,monospace;">watch</span>=
:<br></span><br>=C2=A0 void watch(item const* i) {<br>=C2=A0=C2=A0=C2=A0 if=
 (i) {<br>=C2=A0=C2=A0 =C2=A0=C2=A0 watched_items.push_back(*i);<br>=C2=A0=
=C2=A0=C2=A0 } else {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 throw std::runtime_=
error(&quot;i cannot be null&quot;);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 }</s=
pan><br></div><div><br>Or of course, we can use <span style=3D"font-family:=
 courier new,monospace;">not_null</span> to push the exception further up t=
he call stack:<br>=C2=A0<br><span style=3D"font-family:courier new,monospac=
e">=C2=A0 void watch(not_null&lt;item const*&gt; i) {<br></span><span style=
=3D"font-family:courier new,monospace"><span style=3D"font-family:courier n=
ew,monospace">=C2=A0=C2=A0=C2=A0 </span></span><span style=3D"font-family:c=
ourier new,monospace"><span style=3D"font-family:courier new,monospace"><sp=
an style=3D"font-family:courier new,monospace">watched_items</span>.push_ba=
ck(*i);<br></span>=C2=A0 }</span><br><br>Or, if we can modify the interface=
, we can make the caller responsible for dereferencing their pointer:<br><s=
pan style=3D"font-family:courier new,monospace"><br>=C2=A0 void watch(item =
const&amp; i) {<br></span><span style=3D"font-family:courier new,monospace"=
><span style=3D"font-family:courier new,monospace">=C2=A0=C2=A0=C2=A0 </spa=
n></span><span style=3D"font-family:courier new,monospace"><span style=3D"f=
ont-family:courier new,monospace"><span style=3D"font-family:courier new,mo=
nospace">watched_items</span>.push_back(i);<br></span>=C2=A0 }</span><br><b=
r>Or maybe even:<br><br><span style=3D"font-family:courier new,monospace">=
=C2=A0 void foo(view&lt;item const&gt; i) {<br>=C2=A0=C2=A0=C2=A0 watched_i=
tems.push_back(i);<br>=C2=A0 }</span><br><br>A note about the last two exam=
ples: syntactically they are identical, but semantically they are not. Use =
of view implies that the &quot;reference&quot; may be stored by the class; =
use of reference to const is often done just for performance reasons (to av=
oid making an expensive copy).<br><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div>Let me rephrase that bit at the end.<br=
><br>`view&lt;int&gt;` and `not_null&lt;int*&gt;` have almost exactly the s=
ame interface. The <i>only difference</i> between them is that one takes re=
ferences and the other takes pointers.<br><br>That trivial difference is no=
t worth creating a whole new type for.</div></div></blockquote><div>=C2=A0<=
br>As I hope I&#39;ve demonstrated, taking a pointer makes run time errors =
into compile time errors and pushes those errors up the call stack. I think=
 this is important. I&#39;ve already listed one other reason: semantics. vi=
ew can convey meaning. As for other features, it really is just general syn=
tactic niceness. The design of <span style=3D"font-family: courier new,mono=
space;">view</span> and <span style=3D"font-family: courier new,monospace;"=
>optional_view</span> are still somewhat in flux, but I can think of at lea=
st one other important feature.<br><br>I currently have it so that <span st=
yle=3D"font-family: courier new,monospace;">view&lt;T&gt;</span> is implici=
tly convertible to <span style=3D"font-family: courier new,monospace;">T&am=
p;</span>. This allows you to do things like this:<br><br><span style=3D"fo=
nt-family: courier new,monospace;">=C2=A0 void monitor_items() {<br>=C2=A0=
=C2=A0=C2=A0 for (item const&amp; i : watched_items) {<br>=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 monitor(i);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 }</span><br><=
br>This could be generic code that operates on both containers of <span sty=
le=3D"font-family: courier new,monospace;">T</span> and containers of <span=
 style=3D"font-family: courier new,monospace;">view&lt;T&gt;</span>. Anothe=
r (contrived) example of this feature in use:<br><br><span style=3D"font-fa=
mily: courier new,monospace;">=C2=A0 std::array&lt;int, 3&gt; i =3D { 0, 1,=
 2 };<br>=C2=A0 std::map&lt;std::string, optional_view&lt;int&gt;&gt; m;<br=
><br>=C2=A0 m[&quot;a&quot;] =3D i[0];<br>=C2=A0 m[&quot;b&quot;] =3D i[1];=
<br>=C2=A0 m[&quot;c&quot;] =3D i[2];<br><br>=C2=A0 int&amp; b =3D m[&quot;=
b&quot;];</span><br><br>Here I used <span style=3D"font-family: courier new=
,monospace;">optional_view</span> because it is default constructible. I co=
uld have used <span style=3D"font-family: courier new,monospace;">view</spa=
n> if I had used <span style=3D"font-family: courier new,monospace;">map::e=
mplace</span> and <span style=3D"font-family: courier new,monospace;">map::=
at</span>.<br><br>Note however that <span style=3D"font-family: courier new=
,monospace;">view&lt;T&gt;</span> is not convertible to <span style=3D"font=
-family: courier new,monospace;">T</span>. This is because I want symmetry =
and consistency. <span style=3D"font-family: courier new,monospace;">view</=
span> is not a value type, so I do not want it to be able to implicitly con=
vert to and from other value types. You have to &quot;dereference&quot; it =
to access the underlying value. <span style=3D"font-family: courier new,mon=
ospace;">optional_view&lt;T&gt;</span> also implicitly converts to <span st=
yle=3D"font-family: courier new,monospace;">T&amp;</span>, but throws an ex=
ception if it is empty.<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/dd418983-c40b-4deb-8cff-e004547cc75a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/dd418983-c40b-4deb-8cff-e004547cc75a=
%40isocpp.org</a>.<br />

------=_Part_7416_991757972.1476244467537--

------=_Part_7415_1088349909.1476244467536--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 11 Oct 2016 23:17:19 -0700 (PDT)
Raw View
------=_Part_172_642095997.1476253039536
Content-Type: multipart/alternative;
 boundary="----=_Part_173_118990285.1476253039537"

------=_Part_173_118990285.1476253039537
Content-Type: text/plain; charset=UTF-8

On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, joseph....@gmail.com
wrote:
>
>
>   void foo(not_null<int*> p) { // legacy interface made safer with not_null
>
>>     view<int> v = *p; // modern implementation (static analysis: a-okay)
>>>>     ...
>>>>   }
>>>>
>>>
>>> But why would you use `view<int>` inside of `foo` at all? There would be
>>> no objective *need*, unless you're just allergic to using `->`.
>>>
>>
> It's just a contrived example. I will try to give more practical examples
> from now on (and I assume given your follow-up, you noticed that view does
> require operator->).
>
> One of the main differences between not_null and view is that not_null
>>>> detects null pointer errors at run time, while view catches them at
>>>> compile time.
>>>>
>>>>   void foo(int* p) {
>>>>     not_null<int*> nn = p; // run-time exception
>>>>     view<int> = p; // compile-time error
>>>>   }
>>>>
>>>
>> That's not a NULL pointer check. Nothing ever detects that `p` is a null
>> pointer. It fails to compile only because `view<int>` cannot be constructed
>> from a pointer at all. If you had done `view<int> = *p`, it would compile
>> just fine. What it would not do is actually catch an error if you pass
>> `nullptr` to `foo`. It would simply invoke UB.
>>
>
> This was part of the motivation for my second example. Correct usage would
> be something like this (disclaimer: the example is still somewhat
> contrived). Given some class, watcher:
>
>   class watcher {
>     std::vector<view<item const>> watched_items;
>     ...
>   };
>
> We might implement the method, watch:
>
>   void watch(item const* i) {
>     if (i) {
>       watched_items.push_back(*i);
>     } else {
>       throw std::runtime_error("i cannot be null");
>     }
>   }
>
> Or of course, we can use not_null to push the exception further up the
> call stack:
>
>   void watch(not_null<item const*> i) {
>     watched_items.push_back(*i);
>   }
>
> Or, if we can modify the interface, we can make the caller responsible for
> dereferencing their pointer:
>
>   void watch(item const& i) {
>     watched_items.push_back(i);
>   }
>
> Or maybe even:
>
>   void foo(view<item const> i) {
>     watched_items.push_back(i);
>   }
>
>
A note about the last two examples: syntactically they are identical, but
> semantically they are not. Use of view implies that the "reference" may be
> stored by the class; use of reference to const is often done just for
> performance reasons (to avoid making an expensive copy).
>

The use of a view implies no such thing. Or at least, not in the way
"views" get used in other contexts. `string_view` for example very much *does
not* have this implication. After all, `basic_string` is *implicitly*
convertible to a `string_view`, even from a string temporary. So any code
that takes a `string_view` as a parameter and tries to store it longer-term
is in for a rude awakening.

Why should `view<T>` have different semantics in this regard? It certainly
is not how users would expect it to work.

In any case, it is highly dangerous to store any pointer/reference to an
object in a class without an explicit ownership contract. Not unless you
have special knowledge of the source. And we have a way to represent that
"special knowledge" already. Or more importantly, that the function will
explicitly have some expectation of the object surviving the call stack.

We call that `gsl::owner<T>`. If you wrap your parameter in that, then it
expresses the idea that the function claims some form of ownership of the
object.


> Let me rephrase that bit at the end.
>>
>> `view<int>` and `not_null<int*>` have almost exactly the same interface.
>> The *only difference* between them is that one takes references and the
>> other takes pointers.
>>
>> That trivial difference is not worth creating a whole new type for.
>>
>
> As I hope I've demonstrated, taking a pointer makes run time errors into
> compile time errors and pushes those errors up the call stack.
>

That they push errors up the call stack is true, but just as with
`not_null`, it only does so to the degree that the caller uses the type in
question directly. What `view<T>` doesn't do is actually cause runtime
checks for the error. So if you have a `T*`, and you don't check if it's
NULL, turning it into a `view<T>` is no less dangerous than turning it into
a `not_null<T*>`. Indeed, it's more dangerous, since `not_null` will throw,
while `view<T>` will have no idea that it has a NULL reference.

I have yet to see an example where a runtime error becomes a compile-time
error as you suggest. This code is a potential runtime error:

void foo(T *t)
{
  not_null<T*> nnt = t;
}

Show me the equivalent `view<T>` code that makes this a compile-time error.
But *only when `t` is NULL*. That is, this code should compile fine for any
user who calls `foo` with a not-NULL pointer. But should fail to compile
when `foo` is called with `nullptr`. That's what making "run time errors
into compile time errors" would be; after all, the above code only issues a
runtime error if you *actually call it* with NULL.

If the compile-time version can't compile-time check the pointer's value,
then it's not doing the same work. And therefore, it is not equivalent
code; it'd an apples-to-oranges comparison.

I think this is important. I've already listed one other reason: semantics.
> view can convey meaning. As for other features, it really is just general
> syntactic niceness. The design of view and optional_view are still
> somewhat in flux, but I can think of at least one other important feature.
>
> I currently have it so that view<T> is implicitly convertible to T&. This
> allows you to do things like this:
>
>   void monitor_items() {
>     for (item const& i : watched_items) {
>       monitor(i);
>     }
>   }
>
> This could be generic code that operates on both containers of T and
> containers of view<T>.
>

Generic in what way? Your generic code couldn't actually *do anything* with
the `view<T>`. Not directly. It could pass it to some other functions, to
be sure. But it could only pass it to ones which took the `view<T>`. This
function itself cannot access members of the object directly. It couldn't
send it to any function that took a `const T&`. And so forth.

The only thing that would allow "generic code" to work as you suggest is
operator-dot.

--
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/390cbd81-8e95-4932-9cca-ac58a008f7ec%40isocpp.org.

------=_Part_173_118990285.1476253039537
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, joseph.=
....@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><br><span style=3D"font-family:courier new,monospace">=C2=A0 void =
foo(not_null&lt;int*&gt; p) { // legacy interface made safer with not_null<=
/span><br><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(20=
4,204,204);padding-left:1ex"><span style=3D"font-family:courier new,monospa=
ce">=C2=A0=C2=A0=C2=A0 view&lt;int&gt; v =3D *p; // modern implementation (=
static analysis: a-okay)</span><br><span style=3D"font-family:courier new,m=
onospace">=C2=A0=C2=A0=C2=A0 ...</span><br><span style=3D"font-family:couri=
er new,monospace">=C2=A0 }</span><br></blockquote><br>But why would you use=
 `view&lt;int&gt;` inside of `foo` at all? There would be no objective <i>n=
eed</i>, unless you&#39;re just allergic to using `-&gt;`.<br></div></div><=
/blockquote></div></blockquote><div><br>It&#39;s just a contrived example. =
I will try to give more practical examples from now on (and I assume given =
your follow-up, you noticed that view does require <span style=3D"font-fami=
ly:courier new,monospace">operator-&gt;</span>).<br><br></div><blockquote s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);pad=
ding-left:1ex" class=3D"gmail_quote"><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"><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"=
>One of the main differences between=20
<span style=3D"font-family:courier new,monospace">not_null</span> and <span=
 style=3D"font-family:courier new,monospace">view</span> is that <span styl=
e=3D"font-family:courier new,monospace">not_null</span> detects null pointe=
r errors at run time,=20
while <span style=3D"font-family:courier new,monospace">view</span> catches=
 them at compile time.<br><br><span style=3D"font-family:courier new,monosp=
ace">=C2=A0 void foo(int* p) {<br>=C2=A0 =C2=A0 not_null&lt;int*&gt; nn =3D=
 p; // run-time exception<br>=C2=A0=C2=A0=C2=A0 view&lt;int&gt; =3D p; // c=
ompile-time error<br>=C2=A0 }</span></div></blockquote></div></blockquote><=
br>That&#39;s not a NULL pointer check. Nothing ever detects that `p` is a =
null
 pointer. It fails to compile only because `view&lt;int&gt;` cannot be=20
constructed from a pointer at all. If you had done `view&lt;int&gt; =3D=20
*p`, it would compile just fine. What it would not do is actually catch=20
an error if you pass `nullptr` to `foo`. It would simply invoke UB. <br></b=
lockquote><div><br>This was part of the motivation for my second example. C=
orrect usage would be something like this (disclaimer: the example is still=
 somewhat contrived). Given some class, <span style=3D"font-family:courier =
new,monospace">watcher</span>:<br><br><span style=3D"font-family:courier ne=
w,monospace">=C2=A0 class watcher {<br>=C2=A0 =C2=A0 std::vector&lt;view&lt=
;item const&gt;&gt; watched_items;<br>=C2=A0=C2=A0=C2=A0 ...<br>=C2=A0 };<b=
r><span style=3D"font-family:arial,sans-serif"><br>We might implement the m=
ethod, <span style=3D"font-family:courier new,monospace">watch</span>:<br><=
/span><br>=C2=A0 void watch(item const* i) {<br>=C2=A0=C2=A0=C2=A0 if (i) {=
<br>=C2=A0=C2=A0 =C2=A0=C2=A0 watched_items.push_back(*i);<br>=C2=A0=C2=A0=
=C2=A0 } else {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 throw std::runtime_error(=
&quot;i cannot be null&quot;);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 }</span><b=
r></div><div><br>Or of course, we can use <span style=3D"font-family:courie=
r new,monospace">not_null</span> to push the exception further up the call =
stack:<br>=C2=A0<br><span style=3D"font-family:courier new,monospace">=C2=
=A0 void watch(not_null&lt;item const*&gt; i) {<br></span><span style=3D"fo=
nt-family:courier new,monospace"><span style=3D"font-family:courier new,mon=
ospace">=C2=A0=C2=A0=C2=A0 </span></span><span style=3D"font-family:courier=
 new,monospace"><span style=3D"font-family:courier new,monospace"><span sty=
le=3D"font-family:courier new,monospace">watched_items</span>.push_back(*i)=
;<br></span>=C2=A0 }</span><br><br>Or, if we can modify the interface, we c=
an make the caller responsible for dereferencing their pointer:<br><span st=
yle=3D"font-family:courier new,monospace"><br>=C2=A0 void watch(item const&=
amp; i) {<br></span><span style=3D"font-family:courier new,monospace"><span=
 style=3D"font-family:courier new,monospace">=C2=A0=C2=A0=C2=A0 </span></sp=
an><span style=3D"font-family:courier new,monospace"><span style=3D"font-fa=
mily:courier new,monospace"><span style=3D"font-family:courier new,monospac=
e">watched_items</span>.push_back(i);<br></span>=C2=A0 }</span><br><br>Or m=
aybe even:<br><br><span style=3D"font-family:courier new,monospace">=C2=A0 =
void foo(view&lt;item const&gt; i) {<br>=C2=A0=C2=A0=C2=A0 watched_items.pu=
sh_back(i);<br>=C2=A0 }</span><br>=C2=A0</div></div></blockquote><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>A note about the l=
ast two examples: syntactically they are identical, but semantically they a=
re not. Use of view implies that the &quot;reference&quot; may be stored by=
 the class; use of reference to const is often done just for performance re=
asons (to avoid making an expensive copy).<br></div></div></blockquote><div=
><br>The use of a view implies no such thing. Or at least, not in the way &=
quot;views&quot; get used in=20
other contexts. `string_view` for example very much <i>does not</i> have th=
is implication. After all,=20
`basic_string` is <i>implicitly</i> convertible to a `string_view`, even fr=
om a
string temporary. So any code that takes a `string_view` as a parameter and=
 tries to store it longer-term is in for a rude=20
awakening.<br><br>Why should `view&lt;T&gt;` have different semantics in th=
is regard? It certainly is not how users would expect it to work.<br><br>In
 any case, it is highly dangerous to store any pointer/reference to an=20
object in a class without an explicit ownership contract. Not unless you
 have special knowledge of the source. And we have a way to represent=20
that &quot;special knowledge&quot; already. Or more importantly, that the f=
unction
 will explicitly have some expectation of the object surviving the call=20
stack.<br><br>We call that `gsl::owner&lt;T&gt;`. If you wrap your=20
parameter in that, then it expresses the idea that the function claims=20
some form of ownership of the object.<br>=C2=A0</div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>Let me rephrase that bit at the end.<=
br><br>`view&lt;int&gt;` and `not_null&lt;int*&gt;` have almost exactly the=
 same interface. The <i>only difference</i> between them is that one takes =
references and the other takes pointers.<br><br>That trivial difference is =
not worth creating a whole new type for.</div></div></blockquote><div>=C2=
=A0<br>As I hope I&#39;ve demonstrated, taking a pointer makes run time err=
ors into compile time errors and pushes those errors up the call stack.</di=
v></div></blockquote><div><br>That they push errors up the call stack is tr=
ue, but just as with `not_null`, it only does so to the degree that the cal=
ler uses the type in question directly. What `view&lt;T&gt;` doesn&#39;t do=
 is actually cause runtime checks for the error. So if you have a `T*`, and=
 you don&#39;t check if it&#39;s NULL, turning it into a `view&lt;T&gt;` is=
 no less dangerous than turning it into a `not_null&lt;T*&gt;`. Indeed, it&=
#39;s more dangerous, since `not_null` will throw, while `view&lt;T&gt;` wi=
ll have no idea that it has a NULL reference.<br><br>I have yet to see an e=
xample where a runtime error becomes a compile-time error as you suggest. T=
his code is a potential runtime error:<br><br><div style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><co=
de class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color=
: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">T </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 not_null</span><span s=
tyle=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">*&gt;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> nnt </span><span style=3D"color: #660;" c=
lass=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"styled-by-pretti=
fy"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}<=
/span></div></code></div><br>Show me the equivalent `view&lt;T&gt;` code th=
at makes this a compile-time error. But <i>only when `t` is NULL</i>. That =
is, this code should compile fine for any user who calls `foo` with a not-N=
ULL pointer. But should fail to compile when `foo` is called with `nullptr`=
.. That&#39;s what making &quot;run time errors into compile time errors&quo=
t; would be; after all, the above code only issues a runtime error if you <=
i>actually call it</i> with NULL.<br><br>If the compile-time version can&#3=
9;t compile-time check the pointer&#39;s value, then it&#39;s not doing the=
 same work. And therefore, it is not equivalent code; it&#39;d an apples-to=
-oranges comparison.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div>I think this is important. I&#39;ve already lis=
ted one other reason: semantics. view can convey meaning. As for other feat=
ures, it really is just general syntactic niceness. The design of <span sty=
le=3D"font-family:courier new,monospace">view</span> and <span style=3D"fon=
t-family:courier new,monospace">optional_view</span> are still somewhat in =
flux, but I can think of at least one other important feature.<br><br>I cur=
rently have it so that <span style=3D"font-family:courier new,monospace">vi=
ew&lt;T&gt;</span> is implicitly convertible to <span style=3D"font-family:=
courier new,monospace">T&amp;</span>. This allows you to do things like thi=
s:<br><br><span style=3D"font-family:courier new,monospace">=C2=A0 void mon=
itor_items() {<br>=C2=A0=C2=A0=C2=A0 for (item const&amp; i : watched_items=
) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 monitor(i);<br>=C2=A0=C2=A0=C2=A0 }<b=
r>=C2=A0 }</span><br><br>This could be generic code that operates on both c=
ontainers of <span style=3D"font-family:courier new,monospace">T</span> and=
 containers of <span style=3D"font-family:courier new,monospace">view&lt;T&=
gt;</span>.</div></div></blockquote><div><br>Generic in what way? Your gene=
ric code couldn&#39;t actually *do anything* with the `view&lt;T&gt;`. Not =
directly. It could pass it to some other functions, to be sure. But it coul=
d only pass it to ones which took the `view&lt;T&gt;`. This function itself=
 cannot access members of the object directly. It couldn&#39;t send it to a=
ny function that took a `const T&amp;`. And so forth.<br><br>The only thing=
 that would allow &quot;generic code&quot; to work as you suggest is operat=
or-dot.<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/390cbd81-8e95-4932-9cca-ac58a008f7ec%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/390cbd81-8e95-4932-9cca-ac58a008f7ec=
%40isocpp.org</a>.<br />

------=_Part_173_118990285.1476253039537--

------=_Part_172_642095997.1476253039536--

.


Author: joseph.thomson@gmail.com
Date: Wed, 12 Oct 2016 00:07:15 -0700 (PDT)
Raw View
------=_Part_4445_884393913.1476256035685
Content-Type: multipart/alternative;
 boundary="----=_Part_4446_1506576527.1476256035686"

------=_Part_4446_1506576527.1476256035686
Content-Type: text/plain; charset=UTF-8



On Wednesday, 12 October 2016 14:17:19 UTC+8, Nicol Bolas wrote:
>
> On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, joseph....@gmail.com
> wrote:
>>
>>
>>   void foo(not_null<int*> p) { // legacy interface made safer with
>> not_null
>>
>>>     view<int> v = *p; // modern implementation (static analysis: a-okay)
>>>>>     ...
>>>>>   }
>>>>>
>>>>
>>>> But why would you use `view<int>` inside of `foo` at all? There would
>>>> be no objective *need*, unless you're just allergic to using `->`.
>>>>
>>>
>> It's just a contrived example. I will try to give more practical examples
>> from now on (and I assume given your follow-up, you noticed that view does
>> require operator->).
>>
>> One of the main differences between not_null and view is that not_null
>>>>> detects null pointer errors at run time, while view catches them at
>>>>> compile time.
>>>>>
>>>>>   void foo(int* p) {
>>>>>     not_null<int*> nn = p; // run-time exception
>>>>>     view<int> = p; // compile-time error
>>>>>   }
>>>>>
>>>>
>>> That's not a NULL pointer check. Nothing ever detects that `p` is a null
>>> pointer. It fails to compile only because `view<int>` cannot be constructed
>>> from a pointer at all. If you had done `view<int> = *p`, it would compile
>>> just fine. What it would not do is actually catch an error if you pass
>>> `nullptr` to `foo`. It would simply invoke UB.
>>>
>>
>> This was part of the motivation for my second example. Correct usage
>> would be something like this (disclaimer: the example is still somewhat
>> contrived). Given some class, watcher:
>>
>>   class watcher {
>>     std::vector<view<item const>> watched_items;
>>     ...
>>   };
>>
>> We might implement the method, watch:
>>
>>   void watch(item const* i) {
>>     if (i) {
>>       watched_items.push_back(*i);
>>     } else {
>>       throw std::runtime_error("i cannot be null");
>>     }
>>   }
>>
>> Or of course, we can use not_null to push the exception further up the
>> call stack:
>>
>>   void watch(not_null<item const*> i) {
>>     watched_items.push_back(*i);
>>   }
>>
>> Or, if we can modify the interface, we can make the caller responsible
>> for dereferencing their pointer:
>>
>>   void watch(item const& i) {
>>     watched_items.push_back(i);
>>   }
>>
>> Or maybe even:
>>
>>   void foo(view<item const> i) {
>>     watched_items.push_back(i);
>>   }
>>
>>
> A note about the last two examples: syntactically they are identical, but
>> semantically they are not. Use of view implies that the "reference" may be
>> stored by the class; use of reference to const is often done just for
>> performance reasons (to avoid making an expensive copy).
>>
>
> The use of a view implies no such thing. Or at least, not in the way
> "views" get used in other contexts. `string_view` for example very much *does
> not* have this implication. After all, `basic_string` is *implicitly*
> convertible to a `string_view`, even from a string temporary. So any code
> that takes a `string_view` as a parameter and tries to store it longer-term
> is in for a rude awakening.
>
> Why should `view<T>` have different semantics in this regard? It certainly
> is not how users would expect it to work.
>
> In any case, it is highly dangerous to store any pointer/reference to an
> object in a class without an explicit ownership contract. Not unless you
> have special knowledge of the source. And we have a way to represent that
> "special knowledge" already. Or more importantly, that the function will
> explicitly have some expectation of the object surviving the call stack.
>

> We call that `gsl::owner<T>`. If you wrap your parameter in that, then it
> expresses the idea that the function claims some form of ownership of the
> object.
>

In my example I was obviously assuming special knowledge, as it is indeed
dangerous to store random non-owning references to things. You are right
that use of view doesn't imply long-term storage; that information has to
be conveyed in the API documentation. I was mistaken.

Let me rephrase that bit at the end.
>>>
>>> `view<int>` and `not_null<int*>` have almost exactly the same interface.
>>> The *only difference* between them is that one takes references and the
>>> other takes pointers.
>>>
>>> That trivial difference is not worth creating a whole new type for.
>>>
>>
>> As I hope I've demonstrated, taking a pointer makes run time errors into
>> compile time errors and pushes those errors up the call stack.
>>
>
> That they push errors up the call stack is true, but just as with
> `not_null`, it only does so to the degree that the caller uses the type in
> question directly. What `view<T>` doesn't do is actually cause runtime
> checks for the error. So if you have a `T*`, and you don't check if it's
> NULL, turning it into a `view<T>` is no less dangerous than turning it into
> a `not_null<T*>`. Indeed, it's more dangerous, since `not_null` will throw,
> while `view<T>` will have no idea that it has a NULL reference.
>
> I have yet to see an example where a runtime error becomes a compile-time
> error as you suggest. This code is a potential runtime error:
>
> void foo(T *t)
> {
>   not_null<T*> nnt = t;
> }
>
> Show me the equivalent `view<T>` code that makes this a compile-time
> error. But *only when `t` is NULL*. That is, this code should compile
> fine for any user who calls `foo` with a not-NULL pointer. But should fail
> to compile when `foo` is called with `nullptr`. That's what making "run
> time errors into compile time errors" would be; after all, the above code
> only issues a runtime error if you *actually call it* with NULL.
>
> If the compile-time version can't compile-time check the pointer's value,
> then it's not doing the same work. And therefore, it is not equivalent
> code; it'd an apples-to-oranges comparison.
>

What I mean is that the API of not_null allows for run time errors, while
the API of view doesn't. If you want zero-overhead code, it is desirable to
eliminate run time error checking. When I say it turns a run time error
into a compile time error, I mean it does that by pushing the error up the
stack.


> I think this is important. I've already listed one other reason:
>> semantics. view can convey meaning. As for other features, it really is
>> just general syntactic niceness. The design of view and optional_view
>> are still somewhat in flux, but I can think of at least one other important
>> feature.
>>
>> I currently have it so that view<T> is implicitly convertible to T&.
>> This allows you to do things like this:
>>
>>   void monitor_items() {
>>     for (item const& i : watched_items) {
>>       monitor(i);
>>     }
>>   }
>>
>> This could be generic code that operates on both containers of T and
>> containers of view<T>.
>>
>
> Generic in what way? Your generic code couldn't actually *do anything*
> with the `view<T>`. Not directly. It could pass it to some other functions,
> to be sure. But it could only pass it to ones which took the `view<T>`.
> This function itself cannot access members of the object directly. It
> couldn't send it to any function that took a `const T&`. And so forth.
>
> The only thing that would allow "generic code" to work as you suggest is
> operator-dot.
>

I meant that the code could operate on both containers of T and containers
of view<T>., because view<T> can be converted to T&. This was just a
passing comment though; I wasn't trying to make a genuine case about view
helping to write generic code. Incidentally though, could a proper "smart
reference" which overloaded operator dot be used here? My understanding was
that operator= would apply to the wrapped object (unless it were
implemented in the wrapper, which would break its ref-like behaviour), so
the reference itself wouldn't be copy assignable, which would prohibit
storing it in a std::vector. Genuine question.

--
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/ff9f439a-06fd-472b-8261-2c6f648042f5%40isocpp.org.

------=_Part_4446_1506576527.1476256035686
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Wednesday, 12 October 2016 14:17:19 UTC+8, Nico=
l Bolas  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=
">On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, <a>joseph....@gmail.co=
m</a> 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><s=
pan style=3D"font-family:courier new,monospace">=C2=A0 void foo(not_null&lt=
;int*&gt; p) { // legacy interface made safer with not_null</span><br><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"><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"><div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padd=
ing-left:1ex"><span style=3D"font-family:courier new,monospace">=C2=A0=C2=
=A0=C2=A0 view&lt;int&gt; v =3D *p; // modern implementation (static analys=
is: a-okay)</span><br><span style=3D"font-family:courier new,monospace">=C2=
=A0=C2=A0=C2=A0 ...</span><br><span style=3D"font-family:courier new,monosp=
ace">=C2=A0 }</span><br></blockquote><br>But why would you use `view&lt;int=
&gt;` inside of `foo` at all? There would be no objective <i>need</i>, unle=
ss you&#39;re just allergic to using `-&gt;`.<br></div></div></blockquote><=
/div></blockquote><div><br>It&#39;s just a contrived example. I will try to=
 give more practical examples from now on (and I assume given your follow-u=
p, you noticed that view does require <span style=3D"font-family:courier ne=
w,monospace">operator-&gt;</span>).<br><br></div><blockquote style=3D"margi=
n:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex=
" class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D=
"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">One of the m=
ain differences between=20
<span style=3D"font-family:courier new,monospace">not_null</span> and <span=
 style=3D"font-family:courier new,monospace">view</span> is that <span styl=
e=3D"font-family:courier new,monospace">not_null</span> detects null pointe=
r errors at run time,=20
while <span style=3D"font-family:courier new,monospace">view</span> catches=
 them at compile time.<br><br><span style=3D"font-family:courier new,monosp=
ace">=C2=A0 void foo(int* p) {<br>=C2=A0 =C2=A0 not_null&lt;int*&gt; nn =3D=
 p; // run-time exception<br>=C2=A0=C2=A0=C2=A0 view&lt;int&gt; =3D p; // c=
ompile-time error<br>=C2=A0 }</span></div></blockquote></div></blockquote><=
br>That&#39;s not a NULL pointer check. Nothing ever detects that `p` is a =
null
 pointer. It fails to compile only because `view&lt;int&gt;` cannot be=20
constructed from a pointer at all. If you had done `view&lt;int&gt; =3D=20
*p`, it would compile just fine. What it would not do is actually catch=20
an error if you pass `nullptr` to `foo`. It would simply invoke UB. <br></b=
lockquote><div><br>This was part of the motivation for my second example. C=
orrect usage would be something like this (disclaimer: the example is still=
 somewhat contrived). Given some class, <span style=3D"font-family:courier =
new,monospace">watcher</span>:<br><br><span style=3D"font-family:courier ne=
w,monospace">=C2=A0 class watcher {<br>=C2=A0 =C2=A0 std::vector&lt;view&lt=
;item const&gt;&gt; watched_items;<br>=C2=A0=C2=A0=C2=A0 ...<br>=C2=A0 };<b=
r><span style=3D"font-family:arial,sans-serif"><br>We might implement the m=
ethod, <span style=3D"font-family:courier new,monospace">watch</span>:<br><=
/span><br>=C2=A0 void watch(item const* i) {<br>=C2=A0=C2=A0=C2=A0 if (i) {=
<br>=C2=A0=C2=A0 =C2=A0=C2=A0 watched_items.push_back(*i);<br>=C2=A0=C2=A0=
=C2=A0 } else {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 throw std::runtime_error(=
&quot;i cannot be null&quot;);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 }</span><b=
r></div><div><br>Or of course, we can use <span style=3D"font-family:courie=
r new,monospace">not_null</span> to push the exception further up the call =
stack:<br>=C2=A0<br><span style=3D"font-family:courier new,monospace">=C2=
=A0 void watch(not_null&lt;item const*&gt; i) {<br></span><span style=3D"fo=
nt-family:courier new,monospace"><span style=3D"font-family:courier new,mon=
ospace">=C2=A0=C2=A0=C2=A0 </span></span><span style=3D"font-family:courier=
 new,monospace"><span style=3D"font-family:courier new,monospace"><span sty=
le=3D"font-family:courier new,monospace">watched_items</span>.push_back(*i)=
;<br></span>=C2=A0 }</span><br><br>Or, if we can modify the interface, we c=
an make the caller responsible for dereferencing their pointer:<br><span st=
yle=3D"font-family:courier new,monospace"><br>=C2=A0 void watch(item const&=
amp; i) {<br></span><span style=3D"font-family:courier new,monospace"><span=
 style=3D"font-family:courier new,monospace">=C2=A0=C2=A0=C2=A0 </span></sp=
an><span style=3D"font-family:courier new,monospace"><span style=3D"font-fa=
mily:courier new,monospace"><span style=3D"font-family:courier new,monospac=
e">watched_items</span>.push_back(i);<br></span>=C2=A0 }</span><br><br>Or m=
aybe even:<br><br><span style=3D"font-family:courier new,monospace">=C2=A0 =
void foo(view&lt;item const&gt; i) {<br>=C2=A0=C2=A0=C2=A0 watched_items.pu=
sh_back(i);<br>=C2=A0 }</span><br>=C2=A0</div></div></blockquote><blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
 #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>A note about the last t=
wo examples: syntactically they are identical, but semantically they are no=
t. Use of view implies that the &quot;reference&quot; may be stored by the =
class; use of reference to const is often done just for performance reasons=
 (to avoid making an expensive copy).<br></div></div></blockquote><div><br>=
The use of a view implies no such thing. Or at least, not in the way &quot;=
views&quot; get used in=20
other contexts. `string_view` for example very much <i>does not</i> have th=
is implication. After all,=20
`basic_string` is <i>implicitly</i> convertible to a `string_view`, even fr=
om a
string temporary. So any code that takes a `string_view` as a parameter and=
 tries to store it longer-term is in for a rude=20
awakening.<br><br>Why should `view&lt;T&gt;` have different semantics in th=
is regard? It certainly is not how users would expect it to work.<br><br>In
 any case, it is highly dangerous to store any pointer/reference to an=20
object in a class without an explicit ownership contract. Not unless you
 have special knowledge of the source. And we have a way to represent=20
that &quot;special knowledge&quot; already. Or more importantly, that the f=
unction
 will explicitly have some expectation of the object surviving the call=20
stack. <br></div></div></blockquote><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><br>We call that `gsl::owner&lt;T&gt;`. If you =
wrap your=20
parameter in that, then it expresses the idea that the function claims=20
some form of ownership of the object.<br></div></div></blockquote><div>=C2=
=A0<br>In my example I was obviously assuming special knowledge, as it is i=
ndeed dangerous to store random non-owning references to things. You are ri=
ght that use of <span style=3D"font-family: courier new,monospace;">view</s=
pan> doesn&#39;t imply long-term storage; that information has to be convey=
ed in the API documentation. I was mistaken.<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div>Let me rephrase that bit at the end.<br><br>`view&=
lt;int&gt;` and `not_null&lt;int*&gt;` have almost exactly the same interfa=
ce. The <i>only difference</i> between them is that one takes references an=
d the other takes pointers.<br><br>That trivial difference is not worth cre=
ating a whole new type for.</div></div></blockquote><div>=C2=A0<br>As I hop=
e I&#39;ve demonstrated, taking a pointer makes run time errors into compil=
e time errors and pushes those errors up the call stack.</div></div></block=
quote><div><br>That they push errors up the call stack is true, but just as=
 with `not_null`, it only does so to the degree that the caller uses the ty=
pe in question directly. What `view&lt;T&gt;` doesn&#39;t do is actually ca=
use runtime checks for the error. So if you have a `T*`, and you don&#39;t =
check if it&#39;s NULL, turning it into a `view&lt;T&gt;` is no less danger=
ous than turning it into a `not_null&lt;T*&gt;`. Indeed, it&#39;s more dang=
erous, since `not_null` will throw, while `view&lt;T&gt;` will have no idea=
 that it has a NULL reference.<br><br>I have yet to see an example where a =
runtime error becomes a compile-time error as you suggest. This code is a p=
otential runtime error:<br><br><div style=3D"background-color:rgb(250,250,2=
50);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><cod=
e><div><span style=3D"color:#008">void</span><span style=3D"color:#000"> fo=
o</span><span style=3D"color:#660">(</span><span style=3D"color:#000">T </s=
pan><span style=3D"color:#660">*</span><span style=3D"color:#000">t</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 not_n=
ull</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">=
T</span><span style=3D"color:#660">*&gt;</span><span style=3D"color:#000"> =
nnt </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000">=
 t</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">}</span></div></code></div><br></div></di=
v></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><div>Show me the equivalent `view&lt;T&gt;` code that makes this a compil=
e-time error. But <i>only when `t` is NULL</i>. That is, this code should c=
ompile fine for any user who calls `foo` with a not-NULL pointer. But shoul=
d fail to compile when `foo` is called with `nullptr`. That&#39;s what maki=
ng &quot;run time errors into compile time errors&quot; would be; after all=
, the above code only issues a runtime error if you <i>actually call it</i>=
 with NULL.<br><br>If the compile-time version can&#39;t compile-time check=
 the pointer&#39;s value, then it&#39;s not doing the same work. And theref=
ore, it is not equivalent code; it&#39;d an apples-to-oranges comparison.<b=
r></div></div></blockquote><div><br>What I mean is that the API of <span st=
yle=3D"font-family: courier new,monospace;">not_null</span> allows for run =
time errors, while the API of <span style=3D"font-family: courier new,monos=
pace;">view</span> doesn&#39;t. If you want zero-overhead code, it is desir=
able to eliminate run time error checking. When I say it turns a run time e=
rror into a compile time error, I mean it does that by pushing the error up=
 the stack.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div>I think this is important. I&#39;ve already listed o=
ne other reason: semantics. view can convey meaning. As for other features,=
 it really is just general syntactic niceness. The design of <span style=3D=
"font-family:courier new,monospace">view</span> and <span style=3D"font-fam=
ily:courier new,monospace">optional_view</span> are still somewhat in flux,=
 but I can think of at least one other important feature.<br><br>I currentl=
y have it so that <span style=3D"font-family:courier new,monospace">view&lt=
;T&gt;</span> is implicitly convertible to <span style=3D"font-family:couri=
er new,monospace">T&amp;</span>. This allows you to do things like this:<br=
><br><span style=3D"font-family:courier new,monospace">=C2=A0 void monitor_=
items() {<br>=C2=A0=C2=A0=C2=A0 for (item const&amp; i : watched_items) {<b=
r>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 monitor(i);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=
=A0 }</span><br><br>This could be generic code that operates on both contai=
ners of <span style=3D"font-family:courier new,monospace">T</span> and cont=
ainers of <span style=3D"font-family:courier new,monospace">view&lt;T&gt;</=
span>.</div></div></blockquote><div><br>Generic in what way? Your generic c=
ode couldn&#39;t actually *do anything* with the `view&lt;T&gt;`. Not direc=
tly. It could pass it to some other functions, to be sure. But it could onl=
y pass it to ones which took the `view&lt;T&gt;`. This function itself cann=
ot access members of the object directly. It couldn&#39;t send it to any fu=
nction that took a `const T&amp;`. And so forth.<br><br>The only thing that=
 would allow &quot;generic code&quot; to work as you suggest is operator-do=
t.<br></div></div></blockquote><div><br>I meant that the code could operate=
 on both containers of <span style=3D"font-family: courier new,monospace;">=
T</span> and containers of <span style=3D"font-family: courier new,monospac=
e;">view&lt;T&gt;</span>., because <span style=3D"font-family: courier new,=
monospace;">view&lt;T&gt;</span> can be converted to <span style=3D"font-fa=
mily: courier new,monospace;">T&amp;</span>. This was just a passing commen=
t though; I wasn&#39;t trying to make a genuine case about view helping to =
write generic code. Incidentally though, could a proper &quot;smart referen=
ce&quot; which overloaded operator dot be used here? My understanding was t=
hat <span style=3D"font-family: courier new,monospace;">operator=3D</span> =
would apply to the wrapped object (unless it were implemented in the wrappe=
r, which would break its ref-like behaviour), so the reference itself would=
n&#39;t be copy assignable, which would prohibit storing it in a <span styl=
e=3D"font-family: courier new,monospace;">std::vector</span>. Genuine quest=
ion.<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/ff9f439a-06fd-472b-8261-2c6f648042f5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ff9f439a-06fd-472b-8261-2c6f648042f5=
%40isocpp.org</a>.<br />

------=_Part_4446_1506576527.1476256035686--

------=_Part_4445_884393913.1476256035685--

.


Author: Victor Dyachenko <victor.dyachenko@gmail.com>
Date: Wed, 12 Oct 2016 00:34:09 -0700 (PDT)
Raw View
------=_Part_748_963889620.1476257649737
Content-Type: multipart/alternative;
 boundary="----=_Part_749_1805851020.1476257649738"

------=_Part_749_1805851020.1476257649738
Content-Type: text/plain; charset=UTF-8

What is the difference between std::view and std::reference_wrapper? Just
different syntax here?

std::view<int> v = i;
v = j; // reassignment of the view
*v = 42; // assignment of the referenced object

std::reference_wrapper<int> v = i;
v = std::ref(j); // reassignment of the reference
v.get() = 42; // assignment of the referenced object
//or just
v = 42; // assignment of the referenced object

--
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/53860757-5e7d-4799-a793-b4b25569c2f2%40isocpp.org.

------=_Part_749_1805851020.1476257649738
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">What is the difference between <span style=3D"font-family:=
 courier new,monospace;">std::view</span> and <span style=3D"font-family: c=
ourier new,monospace;">std::reference_wrapper</span>? Just different syntax=
 here?<br><br><span style=3D"font-family:courier new,monospace"> <div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><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"colo=
r: #000;" class=3D"styled-by-prettify">view</span><span style=3D"color: #08=
0;" class=3D"styled-by-prettify">&lt;int&gt;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> v </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> i</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>v </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> j</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #800;" class=3D"styled-by-prettify">// reassignment of the view</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">v </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"=
styled-by-prettify">42</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// ass=
ignment of the referenced object</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span></div></code></div><br></span><span styl=
e=3D"font-family:courier new,monospace"> </span><div class=3D"prettyprint" =
style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, =
187); border-style: solid; border-width: 1px; word-wrap: break-word;"><code=
 class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: =
#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=
"styled-by-prettify">reference_wrapper</span><span style=3D"color: #080;" c=
lass=3D"styled-by-prettify">&lt;int&gt;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> v </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> i</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>v </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D<=
/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 st=
yle=3D"color: #008;" class=3D"styled-by-prettify">ref</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">j</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">// reassignment of the reference</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br>v</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">get</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #066;" class=3D"styled-by-prettify">42</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">// assignment of the referenced object</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">//or just</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>v </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" cl=
ass=3D"styled-by-prettify">42</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>// assignment of the referenced object</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span></div></code></div><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/53860757-5e7d-4799-a793-b4b25569c2f2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/53860757-5e7d-4799-a793-b4b25569c2f2=
%40isocpp.org</a>.<br />

------=_Part_749_1805851020.1476257649738--

------=_Part_748_963889620.1476257649737--

.


Author: joseph.thomson@gmail.com
Date: Wed, 12 Oct 2016 00:52:09 -0700 (PDT)
Raw View
------=_Part_4437_2083586997.1476258730002
Content-Type: multipart/alternative;
 boundary="----=_Part_4438_1848343181.1476258730003"

------=_Part_4438_1848343181.1476258730003
Content-Type: text/plain; charset=UTF-8

Yes, I intended it to have more natural syntax than std::reference_wrapper.
view and optional_view are intended to be used in certain places where
references and pointers are used at the moment, and are designed to be
interoperable. In addition, the way they are designed at the moment, they
are compatible with the proposed std::propagate_const wrapper (implicit
conversion to T& may not work well with this, but like I said, I haven't
figured out all the details).

By the way, I don't think you can do v = 42 with a std::reference_wrapper.
AFAIK, you have to use get.

On Wednesday, 12 October 2016 15:34:10 UTC+8, Victor Dyachenko wrote:
>
> What is the difference between std::view and std::reference_wrapper? Just
> different syntax here?
>
> std::view<int> v = i;
> v = j; // reassignment of the view
> *v = 42; // assignment of the referenced object
>
> std::reference_wrapper<int> v = i;
> v = std::ref(j); // reassignment of the reference
> v.get() = 42; // assignment of the referenced object
> //or just
> v = 42; // assignment of the referenced object
>
>

--
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/f0424841-8423-4cf5-b01b-34fea528b46e%40isocpp.org.

------=_Part_4438_1848343181.1476258730003
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Yes, I intended it to have more natural syntax than <span =
style=3D"font-family: courier new,monospace;">std::reference_wrapper</span>=
.. <span style=3D"font-family: courier new,monospace;">view</span> and <span=
 style=3D"font-family: courier new,monospace;">optional_view</span> are int=
ended to be used in certain places where references and pointers are used a=
t the moment, and are designed to be interoperable. In addition, the way th=
ey are designed at the moment, they are compatible with the proposed <span =
style=3D"font-family: courier new,monospace;">std::propagate_const</span> w=
rapper (implicit conversion to <span style=3D"font-family: courier new,mono=
space;">T&amp;</span> may not work well with this, but like I said, I haven=
&#39;t figured out all the details).<br><br>By the way, I don&#39;t think y=
ou can do <span style=3D"font-family: courier new,monospace;">v =3D 42</spa=
n> with a <span style=3D"font-family: courier new,monospace;">std::referenc=
e_wrapper</span>. AFAIK, you have to use <span style=3D"font-family: courie=
r new,monospace;">get</span>.<br><br>On Wednesday, 12 October 2016 15:34:10=
 UTC+8, Victor Dyachenko  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">What is the difference between <span style=3D"font-famil=
y:courier new,monospace">std::view</span> and <span style=3D"font-family:co=
urier new,monospace">std::reference_wrapper</span>? Just different syntax h=
ere?<br><br><span style=3D"font-family:courier new,monospace"> <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:#000">std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">view</span><span style=3D"color:#080">&lt;int&gt;</span><sp=
an style=3D"color:#000"> v </span><span style=3D"color:#660">=3D</span><spa=
n style=3D"color:#000"> i</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"><br>v </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> j</span><span style=3D"color:#660">;</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#800">// reassignment of the =
view</span><span style=3D"color:#000"><br></span><span style=3D"color:#660"=
>*</span><span style=3D"color:#000">v </span><span style=3D"color:#660">=3D=
</span><span style=3D"color:#000"> </span><span style=3D"color:#066">42</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#800">// assignment of the referenced object</span><span=
 style=3D"color:#000"><br></span></div></code></div><br></span><span style=
=3D"font-family:courier new,monospace"> </span><div style=3D"background-col=
or: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:#000">std<=
/span><span style=3D"color:#660">::</span><span style=3D"color:#000">refere=
nce_wrapper</span><span style=3D"color:#080">&lt;int&gt;</span><span style=
=3D"color:#000"> v </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> i</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"><br>v </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">ref</span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">j</span><span style=3D"color:#660">);</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#800">// reassignment of the referenc=
e</span><span style=3D"color:#000"><br>v</span><span style=3D"color:#660">.=
</span><span style=3D"color:#008">get</span><span style=3D"color:#660">()</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#066">42</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#800">// assignment of the referenced object</span><span styl=
e=3D"color:#000"><br></span><span style=3D"color:#800">//or just</span><spa=
n style=3D"color:#000"><br>v </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#066">42</span><span =
style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#800">// assignment of the referenced object</span><span style=3D=
"color:#000"><br></span></div></code></div><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/f0424841-8423-4cf5-b01b-34fea528b46e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f0424841-8423-4cf5-b01b-34fea528b46e=
%40isocpp.org</a>.<br />

------=_Part_4438_1848343181.1476258730003--

------=_Part_4437_2083586997.1476258730002--

.


Author: Victor Dyachenko <victor.dyachenko@gmail.com>
Date: Wed, 12 Oct 2016 01:05:38 -0700 (PDT)
Raw View
------=_Part_1393_1122352741.1476259538194
Content-Type: multipart/alternative;
 boundary="----=_Part_1394_1892848808.1476259538194"

------=_Part_1394_1892848808.1476259538194
Content-Type: text/plain; charset=UTF-8

On Wednesday, October 12, 2016 at 10:52:10 AM UTC+3, joseph....@gmail.com
wrote:
>
> By the way, I don't think you can do v = 42 with a std::reference_wrapper.
> AFAIK, you have to use get.
>
> Yes..
r = std::ref(value);
and
r = value;
are equivalent.

--
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/a0554a67-930e-4c5c-8780-e477864669d0%40isocpp.org.

------=_Part_1394_1892848808.1476259538194
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, October 12, 2016 at 10:52:10 AM UTC+3, josep=
h....@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">By the way, I don&#39;t think you can do <span style=3D"font-famil=
y:courier new,monospace">v =3D 42</span> with a <span style=3D"font-family:=
courier new,monospace">std::reference_wrapper</span>. AFAIK, you have to us=
e <span style=3D"font-family:courier new,monospace">get</span>.<br><br></di=
v></blockquote><div>Yes..<br><div class=3D"prettyprint" style=3D"background=
-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style:=
 solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">r </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</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: #008;" class=3D"styled-by-prettify">ref</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">value</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span></div></code></div>and<br><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: #000;" class=3D"styled-by-prettify">r </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> value</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">;</span></div></code></div>are equival=
ent.<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/a0554a67-930e-4c5c-8780-e477864669d0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a0554a67-930e-4c5c-8780-e477864669d0=
%40isocpp.org</a>.<br />

------=_Part_1394_1892848808.1476259538194--

------=_Part_1393_1122352741.1476259538194--

.


Author: Victor Dyachenko <victor.dyachenko@gmail.com>
Date: Wed, 12 Oct 2016 01:11:11 -0700 (PDT)
Raw View
------=_Part_937_1474632347.1476259871181
Content-Type: multipart/alternative;
 boundary="----=_Part_938_1223081087.1476259871182"

------=_Part_938_1223081087.1476259871182
Content-Type: text/plain; charset=UTF-8

So difference is just *v vs v.get()

--
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/0bba66f6-358c-493e-a47c-b9887ee46674%40isocpp.org.

------=_Part_938_1223081087.1476259871182
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><span style=3D"font-family:courier new,monospace"><code><s=
pan style=3D"color:#660"><span style=3D"font-family: arial,sans-serif;">So =
difference is just </span><span style=3D"font-family: courier new,monospace=
;">*</span></span><span style=3D"color:#000"><span style=3D"font-family: co=
urier new,monospace;">v</span><span style=3D"font-family: arial,sans-serif;=
"> vs </span>v.get()<br></span></code></span></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/0bba66f6-358c-493e-a47c-b9887ee46674%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0bba66f6-358c-493e-a47c-b9887ee46674=
%40isocpp.org</a>.<br />

------=_Part_938_1223081087.1476259871182--

------=_Part_937_1474632347.1476259871181--

.


Author: joseph.thomson@gmail.com
Date: Wed, 12 Oct 2016 01:31:46 -0700 (PDT)
Raw View
------=_Part_4676_1345854180.1476261106851
Content-Type: multipart/alternative;
 boundary="----=_Part_4677_954174901.1476261106851"

------=_Part_4677_954174901.1476261106851
Content-Type: text/plain; charset=UTF-8

Yes, because it is modelled after other wrapper types like std::unique_ptr
and std::optional. std::reference_wrapper is, as far as I know, intended
for use in implementation code. At least, I've never seen it used in an API.

On Wednesday, 12 October 2016 16:11:11 UTC+8, Victor Dyachenko wrote:
>
> So difference is just *v vs v.get()
>

--
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/3ed0318a-d385-4a5a-b4d4-0df4fcf525d2%40isocpp.org.

------=_Part_4677_954174901.1476261106851
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Yes, because it is modelled after other wrapper types like=
 <span style=3D"font-family: courier new,monospace;">std::unique_ptr</span>=
 and <span style=3D"font-family: courier new,monospace;">std::optional</spa=
n>. std::reference_wrapper is, as far as I know, intended for use in implem=
entation code. At least, I&#39;ve never seen it used in an API.<br><br>On W=
ednesday, 12 October 2016 16:11:11 UTC+8, Victor Dyachenko  wrote:<blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><span style=3D"font-fa=
mily:courier new,monospace"><code><span style=3D"color:#660"><span style=3D=
"font-family:arial,sans-serif">So difference is just </span><span style=3D"=
font-family:courier new,monospace">*</span></span><span style=3D"color:#000=
"><span style=3D"font-family:courier new,monospace">v</span><span style=3D"=
font-family:arial,sans-serif"> vs </span>v.get()<br></span></code></span></=
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/3ed0318a-d385-4a5a-b4d4-0df4fcf525d2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3ed0318a-d385-4a5a-b4d4-0df4fcf525d2=
%40isocpp.org</a>.<br />

------=_Part_4677_954174901.1476261106851--

------=_Part_4676_1345854180.1476261106851--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 12 Oct 2016 06:43:23 -0700 (PDT)
Raw View
------=_Part_1971_1632327099.1476279803927
Content-Type: multipart/alternative;
 boundary="----=_Part_1972_302007203.1476279803928"

------=_Part_1972_302007203.1476279803928
Content-Type: text/plain; charset=UTF-8

On Wednesday, October 12, 2016 at 3:07:15 AM UTC-4, joseph....@gmail.com
wrote:
>
> On Wednesday, 12 October 2016 14:17:19 UTC+8, Nicol Bolas wrote:
>>
>> On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, joseph....@gmail.com
>> wrote:
>>
> Let me rephrase that bit at the end.
>>>>
>>>> `view<int>` and `not_null<int*>` have almost exactly the same
>>>> interface. The *only difference* between them is that one takes
>>>> references and the other takes pointers.
>>>>
>>>> That trivial difference is not worth creating a whole new type for.
>>>>
>>>
>>> As I hope I've demonstrated, taking a pointer makes run time errors into
>>> compile time errors and pushes those errors up the call stack.
>>>
>>
>> That they push errors up the call stack is true, but just as with
>> `not_null`, it only does so to the degree that the caller uses the type in
>> question directly. What `view<T>` doesn't do is actually cause runtime
>> checks for the error. So if you have a `T*`, and you don't check if it's
>> NULL, turning it into a `view<T>` is no less dangerous than turning it into
>> a `not_null<T*>`. Indeed, it's more dangerous, since `not_null` will throw,
>> while `view<T>` will have no idea that it has a NULL reference.
>>
>> I have yet to see an example where a runtime error becomes a compile-time
>> error as you suggest. This code is a potential runtime error:
>>
>> void foo(T *t)
>> {
>>   not_null<T*> nnt = t;
>> }
>>
>> Show me the equivalent `view<T>` code that makes this a compile-time
>> error. But *only when `t` is NULL*. That is, this code should compile
>> fine for any user who calls `foo` with a not-NULL pointer. But should fail
>> to compile when `foo` is called with `nullptr`. That's what making "run
>> time errors into compile time errors" would be; after all, the above code
>> only issues a runtime error if you *actually call it* with NULL.
>>
>> If the compile-time version can't compile-time check the pointer's value,
>> then it's not doing the same work. And therefore, it is not equivalent
>> code; it'd an apples-to-oranges comparison.
>>
>
> What I mean is that the API of not_null allows for run time errors, while
> the API of view doesn't. If you want zero-overhead code, it is desirable
> to eliminate run time error checking. When I say it turns a run time error
> into a compile time error, I mean it does that by pushing the error up the
> stack.
>

Yes. And by doing so, it has pushed it up the stack to the point where it
doesn't actually *check* the error. If the user has a pointer, and they
want to use `view`, it is *the user* who has to test if it isn't NULL.
Whereas `not_null` does the check automatically.

So the above code is safer than this:

void foo(T *t)
{
  view<T> vt = *t; //If null, UB, but nobody checks.
}

Pushing errors "up the stack" is only a good thing if you actually check
for them.


>
> I think this is important. I've already listed one other reason:
>>> semantics. view can convey meaning. As for other features, it really is
>>> just general syntactic niceness. The design of view and optional_view
>>> are still somewhat in flux, but I can think of at least one other important
>>> feature.
>>>
>>> I currently have it so that view<T> is implicitly convertible to T&.
>>> This allows you to do things like this:
>>>
>>>   void monitor_items() {
>>>     for (item const& i : watched_items) {
>>>       monitor(i);
>>>     }
>>>   }
>>>
>>> This could be generic code that operates on both containers of T and
>>> containers of view<T>.
>>>
>>
>> Generic in what way? Your generic code couldn't actually *do anything*
>> with the `view<T>`. Not directly. It could pass it to some other functions,
>> to be sure. But it could only pass it to ones which took the `view<T>`.
>> This function itself cannot access members of the object directly. It
>> couldn't send it to any function that took a `const T&`. And so forth.
>>
>> The only thing that would allow "generic code" to work as you suggest is
>> operator-dot.
>>
>
> I meant that the code could operate on both containers of T and
> containers of view<T>., because view<T> can be converted to T&. This was
> just a passing comment though; I wasn't trying to make a genuine case about
> view helping to write generic code. Incidentally though, could a proper
> "smart reference" which overloaded operator dot be used here? My
> understanding was that operator= would apply to the wrapped object
> (unless it were implemented in the wrapper, which would break its ref-like
> behaviour), so the reference itself wouldn't be copy assignable, which
> would prohibit storing it in a std::vector. Genuine question.
>

With operator-dot, attempting to call `operator=(const smart_ref<T>&)`
would apply to the smart reference. Attempts to use `operator=(const T&)`
would be forwarded to `T`. So smart references could be copy-assignable if
you want, without breaking the ability to treat them as references.

--
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/618deb4f-3912-4f97-9c62-6b3bec858272%40isocpp.org.

------=_Part_1972_302007203.1476279803928
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, October 12, 2016 at 3:07:15 AM UTC-4, joseph=
.....@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Wednesday, 12 October 2016 14:17:19 UTC+8, Nicol Bolas  wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div>On Tuesday, October 11, 2016 at=
 11:54:27 PM UTC-4, <a>joseph....@gmail.com</a> wrote:<br></div></blockquot=
e><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div></div><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"><div>Let me rephrase that bit at the end.=
<br><br>`view&lt;int&gt;` and `not_null&lt;int*&gt;` have almost exactly th=
e same interface. The <i>only difference</i> between them is that one takes=
 references and the other takes pointers.<br><br>That trivial difference is=
 not worth creating a whole new type for.</div></div></blockquote><div>=C2=
=A0<br>As I hope I&#39;ve demonstrated, taking a pointer makes run time err=
ors into compile time errors and pushes those errors up the call stack.</di=
v></div></blockquote><div><br>That they push errors up the call stack is tr=
ue, but just as with `not_null`, it only does so to the degree that the cal=
ler uses the type in question directly. What `view&lt;T&gt;` doesn&#39;t do=
 is actually cause runtime checks for the error. So if you have a `T*`, and=
 you don&#39;t check if it&#39;s NULL, turning it into a `view&lt;T&gt;` is=
 no less dangerous than turning it into a `not_null&lt;T*&gt;`. Indeed, it&=
#39;s more dangerous, since `not_null` will throw, while `view&lt;T&gt;` wi=
ll have no idea that it has a NULL reference.<br><br>I have yet to see an e=
xample where a runtime error becomes a compile-time error as you suggest. T=
his code is a potential runtime error:<br><br><div style=3D"background-colo=
r:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-=
width:1px"><code><div><span style=3D"color:#008">void</span><span style=3D"=
color:#000"> foo</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#000">T </span><span style=3D"color:#660">*</span><span style=3D"color:=
#000">t</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>=C2=A0 not_null</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#000">T</span><span style=3D"color:#660">*&gt;</span><span style=
=3D"color:#000"> nnt </span><span style=3D"color:#660">=3D</span><span styl=
e=3D"color:#000"> t</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#660">}</span></div></code></d=
iv><br></div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div>Show me the equivalent `view&lt;T&gt;` code that makes t=
his a compile-time error. But <i>only when `t` is NULL</i>. That is, this c=
ode should compile fine for any user who calls `foo` with a not-NULL pointe=
r. But should fail to compile when `foo` is called with `nullptr`. That&#39=
;s what making &quot;run time errors into compile time errors&quot; would b=
e; after all, the above code only issues a runtime error if you <i>actually=
 call it</i> with NULL.<br><br>If the compile-time version can&#39;t compil=
e-time check the pointer&#39;s value, then it&#39;s not doing the same work=
.. And therefore, it is not equivalent code; it&#39;d an apples-to-oranges c=
omparison.<br></div></div></blockquote><div><br>What I mean is that the API=
 of <span style=3D"font-family:courier new,monospace">not_null</span> allow=
s for run time errors, while the API of <span style=3D"font-family:courier =
new,monospace">view</span> doesn&#39;t. If you want zero-overhead code, it =
is desirable to eliminate run time error checking. When I say it turns a ru=
n time error into a compile time error, I mean it does that by pushing the =
error up the stack.</div></div></blockquote><div><br>Yes. And by doing so, =
it has pushed it up the stack to the point where it doesn&#39;t actually <i=
>check</i> the error. If the user has a pointer, and they want to use `view=
`, it is *the user* who has to test if it isn&#39;t NULL. Whereas `not_null=
` does the check automatically.<br><br>So the above code is safer than this=
:<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"color: #008;" class=3D"styled-by-prettif=
y">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> fo=
o</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">T </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">t</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 view</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> vt </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an 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">t</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by=
-prettify">//If null, UB, but nobody checks.</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span></div></code></div><br>Pushing errors &quot;u=
p the stack&quot; is only a good thing if you actually check for them.<br>=
=C2=A0</div><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"><=
div> <br></div><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"><di=
v></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>I thi=
nk this is important. I&#39;ve already listed one other reason: semantics. =
view can convey meaning. As for other features, it really is just general s=
yntactic niceness. The design of <span style=3D"font-family:courier new,mon=
ospace">view</span> and <span style=3D"font-family:courier new,monospace">o=
ptional_view</span> are still somewhat in flux, but I can think of at least=
 one other important feature.<br><br>I currently have it so that <span styl=
e=3D"font-family:courier new,monospace">view&lt;T&gt;</span> is implicitly =
convertible to <span style=3D"font-family:courier new,monospace">T&amp;</sp=
an>. This allows you to do things like this:<br><br><span style=3D"font-fam=
ily:courier new,monospace">=C2=A0 void monitor_items() {<br>=C2=A0=C2=A0=C2=
=A0 for (item const&amp; i : watched_items) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 monitor(i);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 }</span><br><br>This c=
ould be generic code that operates on both containers of <span style=3D"fon=
t-family:courier new,monospace">T</span> and containers of <span style=3D"f=
ont-family:courier new,monospace">view&lt;T&gt;</span>.</div></div></blockq=
uote><div><br>Generic in what way? Your generic code couldn&#39;t actually =
*do anything* with the `view&lt;T&gt;`. Not directly. It could pass it to s=
ome other functions, to be sure. But it could only pass it to ones which to=
ok the `view&lt;T&gt;`. This function itself cannot access members of the o=
bject directly. It couldn&#39;t send it to any function that took a `const =
T&amp;`. And so forth.<br><br>The only thing that would allow &quot;generic=
 code&quot; to work as you suggest is operator-dot.<br></div></div></blockq=
uote><div><br>I meant that the code could operate on both containers of <sp=
an style=3D"font-family:courier new,monospace">T</span> and containers of <=
span style=3D"font-family:courier new,monospace">view&lt;T&gt;</span>., bec=
ause <span style=3D"font-family:courier new,monospace">view&lt;T&gt;</span>=
 can be converted to <span style=3D"font-family:courier new,monospace">T&am=
p;</span>. This was just a passing comment though; I wasn&#39;t trying to m=
ake a genuine case about view helping to write generic code. Incidentally t=
hough, could a proper &quot;smart reference&quot; which overloaded operator=
 dot be used here? My understanding was that <span style=3D"font-family:cou=
rier new,monospace">operator=3D</span> would apply to the wrapped object (u=
nless it were implemented in the wrapper, which would break its ref-like be=
haviour), so the reference itself wouldn&#39;t be copy assignable, which wo=
uld prohibit storing it in a <span style=3D"font-family:courier new,monospa=
ce">std::vector</span>. Genuine question.<br></div></div></blockquote><div>=
<br>With operator-dot, attempting to call `operator=3D(const smart_ref&lt;T=
&gt;&amp;)` would apply to the smart reference. Attempts to use `operator=
=3D(const T&amp;)` would be forwarded to `T`. So smart references could be =
copy-assignable if you want, without breaking the ability to treat them as =
references.<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/618deb4f-3912-4f97-9c62-6b3bec858272%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/618deb4f-3912-4f97-9c62-6b3bec858272=
%40isocpp.org</a>.<br />

------=_Part_1972_302007203.1476279803928--

------=_Part_1971_1632327099.1476279803927--

.


Author: joseph.thomson@gmail.com
Date: Wed, 12 Oct 2016 08:47:20 -0700 (PDT)
Raw View
------=_Part_4906_1283511346.1476287241011
Content-Type: multipart/alternative;
 boundary="----=_Part_4907_1772965241.1476287241011"

------=_Part_4907_1772965241.1476287241011
Content-Type: text/plain; charset=UTF-8



On Wednesday, 12 October 2016 21:43:24 UTC+8, Nicol Bolas wrote:
>
> On Wednesday, October 12, 2016 at 3:07:15 AM UTC-4, joseph....@gmail.com
> wrote:
>>
>> On Wednesday, 12 October 2016 14:17:19 UTC+8, Nicol Bolas wrote:
>>>
>>> On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, joseph....@gmail.com
>>> wrote:
>>>
>> Let me rephrase that bit at the end.
>>>>>
>>>>> `view<int>` and `not_null<int*>` have almost exactly the same
>>>>> interface. The *only difference* between them is that one takes
>>>>> references and the other takes pointers.
>>>>>
>>>>> That trivial difference is not worth creating a whole new type for.
>>>>>
>>>>
>>>> As I hope I've demonstrated, taking a pointer makes run time errors
>>>> into compile time errors and pushes those errors up the call stack.
>>>>
>>>
>>> That they push errors up the call stack is true, but just as with
>>> `not_null`, it only does so to the degree that the caller uses the type in
>>> question directly. What `view<T>` doesn't do is actually cause runtime
>>> checks for the error. So if you have a `T*`, and you don't check if it's
>>> NULL, turning it into a `view<T>` is no less dangerous than turning it into
>>> a `not_null<T*>`. Indeed, it's more dangerous, since `not_null` will throw,
>>> while `view<T>` will have no idea that it has a NULL reference.
>>>
>>> I have yet to see an example where a runtime error becomes a
>>> compile-time error as you suggest. This code is a potential runtime error:
>>>
>>> void foo(T *t)
>>> {
>>>   not_null<T*> nnt = t;
>>> }
>>>
>>> Show me the equivalent `view<T>` code that makes this a compile-time
>>> error. But *only when `t` is NULL*. That is, this code should compile
>>> fine for any user who calls `foo` with a not-NULL pointer. But should fail
>>> to compile when `foo` is called with `nullptr`. That's what making "run
>>> time errors into compile time errors" would be; after all, the above code
>>> only issues a runtime error if you *actually call it* with NULL.
>>>
>>> If the compile-time version can't compile-time check the pointer's
>>> value, then it's not doing the same work. And therefore, it is not
>>> equivalent code; it'd an apples-to-oranges comparison.
>>>
>>
>> What I mean is that the API of not_null allows for run time errors,
>> while the API of view doesn't. If you want zero-overhead code, it is
>> desirable to eliminate run time error checking. When I say it turns a run
>> time error into a compile time error, I mean it does that by pushing the
>> error up the stack.
>>
>
> Yes. And by doing so, it has pushed it up the stack to the point where it
> doesn't actually *check* the error. If the user has a pointer, and they
> want to use `view`, it is *the user* who has to test if it isn't NULL.
> Whereas `not_null` does the check automatically.
>
> So the above code is safer than this:
>
> void foo(T *t)
> {
>   view<T> vt = *t; //If null, UB, but nobody checks.
> }
>
> Pushing errors "up the stack" is only a good thing if you actually check
> for them.
>

That's my point: it's the user's responsibility to check that the pointer
isn't null before dereferencing it. Sure, not_null turns potential UB into
an exception, but at a performance cost (a run time check, and possible
overhead relating to exceptions). By using not_null in our interface, we
impose a performance cost (however small) on the user whether or not it's
even possible for them to pass a null pointer. Using view (or a plain
reference) allows our interface to have zero run time overhead; we just
have to trust the user not to dereference any null pointers they may have
hanging around. But ultimately, even if we use not_null, the user can still
dereference null pointers all day long. If we wanted to eliminate this
possibility, we would be better off encouraging the use of an alternative
to pointers which had no null state -- perhaps something like view :)


>> I think this is important. I've already listed one other reason:
>>>> semantics. view can convey meaning. As for other features, it really is
>>>> just general syntactic niceness. The design of view and optional_view
>>>> are still somewhat in flux, but I can think of at least one other important
>>>> feature.
>>>>
>>>> I currently have it so that view<T> is implicitly convertible to T&.
>>>> This allows you to do things like this:
>>>>
>>>>   void monitor_items() {
>>>>     for (item const& i : watched_items) {
>>>>       monitor(i);
>>>>     }
>>>>   }
>>>>
>>>> This could be generic code that operates on both containers of T and
>>>> containers of view<T>.
>>>>
>>>
>>> Generic in what way? Your generic code couldn't actually *do anything*
>>> with the `view<T>`. Not directly. It could pass it to some other functions,
>>> to be sure. But it could only pass it to ones which took the `view<T>`.
>>> This function itself cannot access members of the object directly. It
>>> couldn't send it to any function that took a `const T&`. And so forth.
>>>
>>> The only thing that would allow "generic code" to work as you suggest is
>>> operator-dot.
>>>
>>
>> I meant that the code could operate on both containers of T and
>> containers of view<T>., because view<T> can be converted to T&. This was
>> just a passing comment though; I wasn't trying to make a genuine case about
>> view helping to write generic code. Incidentally though, could a proper
>> "smart reference" which overloaded operator dot be used here? My
>> understanding was that operator= would apply to the wrapped object
>> (unless it were implemented in the wrapper, which would break its ref-like
>> behaviour), so the reference itself wouldn't be copy assignable, which
>> would prohibit storing it in a std::vector. Genuine question.
>>
>
> With operator-dot, attempting to call `operator=(const smart_ref<T>&)`
> would apply to the smart reference. Attempts to use `operator=(const T&)`
> would be forwarded to `T`. So smart references could be copy-assignable if
> you want, without breaking the ability to treat them as references.
>

Really? In that case, they can be stored in containers, but they don't
really behave 100% like references.

  int a = 0;
  int b = 0;

  int& ra = a;
  int& rb = b;

  ra = rb; // copies referenced value

  smart_ref<int> sra = a;
  smart_ref<int> srb = b;

  sra = srb; // rebinds reference

I thought the proposal suggested using a special "rebind" function so that
smart references behave exactly like regular references?

--
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/887a0fb4-f574-4c74-9d65-097fb008195c%40isocpp.org.

------=_Part_4907_1772965241.1476287241011
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Wednesday, 12 October 2016 21:43:24 UTC+8, Nico=
l Bolas  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=
">On Wednesday, October 12, 2016 at 3:07:15 AM UTC-4, <a>joseph....@gmail.c=
om</a> 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">On We=
dnesday, 12 October 2016 14:17:19 UTC+8, Nicol Bolas  wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
 solid;padding-left:1ex"><div>On Tuesday, October 11, 2016 at 11:54:27 PM U=
TC-4, <a>joseph....@gmail.com</a> wrote:<br></div></blockquote><blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div>Let me rephrase that bit at the end.<br><br>`view&=
lt;int&gt;` and `not_null&lt;int*&gt;` have almost exactly the same interfa=
ce. The <i>only difference</i> between them is that one takes references an=
d the other takes pointers.<br><br>That trivial difference is not worth cre=
ating a whole new type for.</div></div></blockquote><div>=C2=A0<br>As I hop=
e I&#39;ve demonstrated, taking a pointer makes run time errors into compil=
e time errors and pushes those errors up the call stack.</div></div></block=
quote><div><br>That they push errors up the call stack is true, but just as=
 with `not_null`, it only does so to the degree that the caller uses the ty=
pe in question directly. What `view&lt;T&gt;` doesn&#39;t do is actually ca=
use runtime checks for the error. So if you have a `T*`, and you don&#39;t =
check if it&#39;s NULL, turning it into a `view&lt;T&gt;` is no less danger=
ous than turning it into a `not_null&lt;T*&gt;`. Indeed, it&#39;s more dang=
erous, since `not_null` will throw, while `view&lt;T&gt;` will have no idea=
 that it has a NULL reference.<br><br>I have yet to see an example where a =
runtime error becomes a compile-time error as you suggest. This code is a p=
otential runtime error:<br><br><div style=3D"background-color:rgb(250,250,2=
50);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><cod=
e><div><span style=3D"color:#008">void</span><span style=3D"color:#000"> fo=
o</span><span style=3D"color:#660">(</span><span style=3D"color:#000">T </s=
pan><span style=3D"color:#660">*</span><span style=3D"color:#000">t</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 not_n=
ull</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">=
T</span><span style=3D"color:#660">*&gt;</span><span style=3D"color:#000"> =
nnt </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000">=
 t</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">}</span></div></code></div><br></div></di=
v></blockquote><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"><di=
v>Show me the equivalent `view&lt;T&gt;` code that makes this a compile-tim=
e error. But <i>only when `t` is NULL</i>. That is, this code should compil=
e fine for any user who calls `foo` with a not-NULL pointer. But should fai=
l to compile when `foo` is called with `nullptr`. That&#39;s what making &q=
uot;run time errors into compile time errors&quot; would be; after all, the=
 above code only issues a runtime error if you <i>actually call it</i> with=
 NULL.<br><br>If the compile-time version can&#39;t compile-time check the =
pointer&#39;s value, then it&#39;s not doing the same work. And therefore, =
it is not equivalent code; it&#39;d an apples-to-oranges comparison.<br></d=
iv></div></blockquote><div><br>What I mean is that the API of <span style=
=3D"font-family:courier new,monospace">not_null</span> allows for run time =
errors, while the API of <span style=3D"font-family:courier new,monospace">=
view</span> doesn&#39;t. If you want zero-overhead code, it is desirable to=
 eliminate run time error checking. When I say it turns a run time error in=
to a compile time error, I mean it does that by pushing the error up the st=
ack.</div></div></blockquote><div><br>Yes. And by doing so, it has pushed i=
t up the stack to the point where it doesn&#39;t actually <i>check</i> the =
error. If the user has a pointer, and they want to use `view`, it is *the u=
ser* who has to test if it isn&#39;t NULL. Whereas `not_null` does the chec=
k automatically.<br><br>So the above code is safer than this:<br><br><div s=
tyle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bor=
der-style:solid;border-width:1px"><code><div><span style=3D"color:#008">voi=
d</span><span style=3D"color:#000"> foo</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#000">T </span><span style=3D"color:#660">*</spa=
n><span style=3D"color:#000">t</span><span style=3D"color:#660">)</span><sp=
an style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span=
 style=3D"color:#000"><br>=C2=A0 view</span><span style=3D"color:#660">&lt;=
</span><span style=3D"color:#000">T</span><span style=3D"color:#660">&gt;</=
span><span style=3D"color:#000"> vt </span><span style=3D"color:#660">=3D</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">*</span>=
<span style=3D"color:#000">t</span><span style=3D"color:#660">;</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#800">//If null, UB, but=
 nobody checks.</span><span style=3D"color:#000"><br></span><span style=3D"=
color:#660">}</span><span style=3D"color:#000"><br></span></div></code></di=
v><br>Pushing errors &quot;up the stack&quot; is only a good thing if you a=
ctually check for them.<br></div></div></blockquote><div><br>That&#39;s my =
point: it&#39;s the user&#39;s responsibility to check that the pointer isn=
&#39;t null before dereferencing it. Sure, <span style=3D"font-family: cour=
ier new,monospace;">not_null</span> turns potential UB into an exception, b=
ut at a performance cost (a run time check, and possible overhead relating =
to exceptions). By using <span style=3D"font-family: courier new,monospace;=
">not_null</span> in our interface, we impose a performance cost (however s=
mall) on the user whether or not it&#39;s even possible for them to pass a =
null pointer. Using <span style=3D"font-family: courier new,monospace;">vie=
w</span> (or a plain reference) allows our interface to have zero run time =
overhead; we just have to trust the user not to dereference any null pointe=
rs they may have hanging around. But ultimately, even if we use <span style=
=3D"font-family: courier new,monospace;">not_null</span>, the user can stil=
l dereference null pointers all day long. If we wanted to eliminate this po=
ssibility, we would be better off encouraging the use of an alternative to =
pointers which had no null state -- perhaps something like <span style=3D"f=
ont-family: courier new,monospace;">view</span> :)<br><br></div><blockquote=
 class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div> <br></div><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"><div></div><blockquote class=3D"gmail_quote"=
 style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div>I think this is important. I&#39;ve already li=
sted one other reason: semantics. view can convey meaning. As for other fea=
tures, it really is just general syntactic niceness. The design of <span st=
yle=3D"font-family:courier new,monospace">view</span> and <span style=3D"fo=
nt-family:courier new,monospace">optional_view</span> are still somewhat in=
 flux, but I can think of at least one other important feature.<br><br>I cu=
rrently have it so that <span style=3D"font-family:courier new,monospace">v=
iew&lt;T&gt;</span> is implicitly convertible to <span style=3D"font-family=
:courier new,monospace">T&amp;</span>. This allows you to do things like th=
is:<br><br><span style=3D"font-family:courier new,monospace">=C2=A0 void mo=
nitor_items() {<br>=C2=A0=C2=A0=C2=A0 for (item const&amp; i : watched_item=
s) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 monitor(i);<br>=C2=A0=C2=A0=C2=A0 }<=
br>=C2=A0 }</span><br><br>This could be generic code that operates on both =
containers of <span style=3D"font-family:courier new,monospace">T</span> an=
d containers of <span style=3D"font-family:courier new,monospace">view&lt;T=
&gt;</span>.</div></div></blockquote><div><br>Generic in what way? Your gen=
eric code couldn&#39;t actually *do anything* with the `view&lt;T&gt;`. Not=
 directly. It could pass it to some other functions, to be sure. But it cou=
ld only pass it to ones which took the `view&lt;T&gt;`. This function itsel=
f cannot access members of the object directly. It couldn&#39;t send it to =
any function that took a `const T&amp;`. And so forth.<br><br>The only thin=
g that would allow &quot;generic code&quot; to work as you suggest is opera=
tor-dot.<br></div></div></blockquote><div><br>I meant that the code could o=
perate on both containers of <span style=3D"font-family:courier new,monospa=
ce">T</span> and containers of <span style=3D"font-family:courier new,monos=
pace">view&lt;T&gt;</span>., because <span style=3D"font-family:courier new=
,monospace">view&lt;T&gt;</span> can be converted to <span style=3D"font-fa=
mily:courier new,monospace">T&amp;</span>. This was just a passing comment =
though; I wasn&#39;t trying to make a genuine case about view helping to wr=
ite generic code. Incidentally though, could a proper &quot;smart reference=
&quot; which overloaded operator dot be used here? My understanding was tha=
t <span style=3D"font-family:courier new,monospace">operator=3D</span> woul=
d apply to the wrapped object (unless it were implemented in the wrapper, w=
hich would break its ref-like behaviour), so the reference itself wouldn&#3=
9;t be copy assignable, which would prohibit storing it in a <span style=3D=
"font-family:courier new,monospace">std::vector</span>. Genuine question.<b=
r></div></div></blockquote><div><br>With operator-dot, attempting to call `=
operator=3D(const smart_ref&lt;T&gt;&amp;)` would apply to the smart refere=
nce. Attempts to use `operator=3D(const T&amp;)` would be forwarded to `T`.=
 So smart references could be copy-assignable if you want, without breaking=
 the ability to treat them as references.<br></div></div></blockquote><div>=
<br>Really? In that case, they can be stored in containers, but they don&#3=
9;t really behave 100% like references.<br><br><span style=3D"font-family: =
courier new,monospace;">=C2=A0 int a =3D 0;<br>=C2=A0 int b =3D 0;<br><br>=
=C2=A0 int&amp; ra =3D a;<br>=C2=A0 int&amp; rb =3D b;<br><br>=C2=A0 ra =3D=
 rb; // copies referenced value<br><br>=C2=A0 smart_ref&lt;int&gt; sra =3D =
a;<br>=C2=A0 smart_ref&lt;int&gt; srb =3D b;<br><br>=C2=A0 sra =3D srb; // =
rebinds reference</span><br><br>I thought the proposal suggested using a sp=
ecial &quot;rebind&quot; function so that smart references behave exactly l=
ike regular references?<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/887a0fb4-f574-4c74-9d65-097fb008195c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/887a0fb4-f574-4c74-9d65-097fb008195c=
%40isocpp.org</a>.<br />

------=_Part_4907_1772965241.1476287241011--

------=_Part_4906_1283511346.1476287241011--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 12 Oct 2016 11:31:05 -0700 (PDT)
Raw View
------=_Part_226_2021079088.1476297066079
Content-Type: multipart/alternative;
 boundary="----=_Part_227_384558825.1476297066079"

------=_Part_227_384558825.1476297066079
Content-Type: text/plain; charset=UTF-8

On Wednesday, October 12, 2016 at 11:47:21 AM UTC-4, joseph....@gmail.com
wrote:
>
> On Wednesday, 12 October 2016 21:43:24 UTC+8, Nicol Bolas wrote:
>>
>> On Wednesday, October 12, 2016 at 3:07:15 AM UTC-4, joseph....@gmail.com
>> wrote:
>>>
>>> On Wednesday, 12 October 2016 14:17:19 UTC+8, Nicol Bolas wrote:
>>>>
>>>> On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, joseph....@gmail.com
>>>> wrote:
>>>>
>>> Let me rephrase that bit at the end.
>>>>>>
>>>>>> `view<int>` and `not_null<int*>` have almost exactly the same
>>>>>> interface. The *only difference* between them is that one takes
>>>>>> references and the other takes pointers.
>>>>>>
>>>>>> That trivial difference is not worth creating a whole new type for.
>>>>>>
>>>>>
>>>>> As I hope I've demonstrated, taking a pointer makes run time errors
>>>>> into compile time errors and pushes those errors up the call stack.
>>>>>
>>>>
>>>> That they push errors up the call stack is true, but just as with
>>>> `not_null`, it only does so to the degree that the caller uses the type in
>>>> question directly. What `view<T>` doesn't do is actually cause runtime
>>>> checks for the error. So if you have a `T*`, and you don't check if it's
>>>> NULL, turning it into a `view<T>` is no less dangerous than turning it into
>>>> a `not_null<T*>`. Indeed, it's more dangerous, since `not_null` will throw,
>>>> while `view<T>` will have no idea that it has a NULL reference.
>>>>
>>>> I have yet to see an example where a runtime error becomes a
>>>> compile-time error as you suggest. This code is a potential runtime error:
>>>>
>>>> void foo(T *t)
>>>> {
>>>>   not_null<T*> nnt = t;
>>>> }
>>>>
>>>> Show me the equivalent `view<T>` code that makes this a compile-time
>>>> error. But *only when `t` is NULL*. That is, this code should compile
>>>> fine for any user who calls `foo` with a not-NULL pointer. But should fail
>>>> to compile when `foo` is called with `nullptr`. That's what making "run
>>>> time errors into compile time errors" would be; after all, the above code
>>>> only issues a runtime error if you *actually call it* with NULL.
>>>>
>>>> If the compile-time version can't compile-time check the pointer's
>>>> value, then it's not doing the same work. And therefore, it is not
>>>> equivalent code; it'd an apples-to-oranges comparison.
>>>>
>>>
>>> What I mean is that the API of not_null allows for run time errors,
>>> while the API of view doesn't. If you want zero-overhead code, it is
>>> desirable to eliminate run time error checking. When I say it turns a run
>>> time error into a compile time error, I mean it does that by pushing the
>>> error up the stack.
>>>
>>
>> Yes. And by doing so, it has pushed it up the stack to the point where it
>> doesn't actually *check* the error. If the user has a pointer, and they
>> want to use `view`, it is *the user* who has to test if it isn't NULL.
>> Whereas `not_null` does the check automatically.
>>
>> So the above code is safer than this:
>>
>> void foo(T *t)
>> {
>>   view<T> vt = *t; //If null, UB, but nobody checks.
>> }
>>
>> Pushing errors "up the stack" is only a good thing if you actually check
>> for them.
>>
>
> That's my point: it's the user's responsibility to check that the pointer
> isn't null before dereferencing it. Sure, not_null turns potential UB
> into an exception, but at a performance cost (a run time check, and
> possible overhead relating to exceptions). By using not_null in our
> interface, we impose a performance cost (however small) on the user whether
> or not it's even possible for them to pass a null pointer. Using view (or
> a plain reference) allows our interface to have zero run time overhead; we
> just have to trust the user not to dereference any null pointers they may
> have hanging around. But ultimately, even if we use not_null, the user
> can still dereference null pointers all day long. If we wanted to eliminate
> this possibility, we would be better off encouraging the use of an
> alternative to pointers which had no null state -- perhaps something like
> view :)
>

I admit that `not_null<T*>` would be better if it could be constructed from
a `T&`, which would also cause it to not bother checking if it is a null
reference. And I have made such a suggestion
<https://github.com/Microsoft/GSL/issues/396>.

But regardless, I don't really understand what you're getting at here.

OK, you have some function that takes a pointer. And your function
implicitly requires that this pointer not be NULL; therefore, it isn't
going to check to see if it's NULL or not. And you intend to store this
not-null pointer around for a time and use it later.

Then why do you not simply *store a pointer*? Why do you need `view<T>`
instead of `T*`? Your code already assumes it's not NULL; what do you gain
from using this type instead of `T*`? That you initialize it with `T&`
rather than `T*`? You still have to use `*` and `->` to access the `T`.


>>> I think this is important. I've already listed one other reason:
>>>>> semantics. view can convey meaning. As for other features, it really is
>>>>> just general syntactic niceness. The design of view and optional_view
>>>>> are still somewhat in flux, but I can think of at least one other important
>>>>> feature.
>>>>>
>>>>> I currently have it so that view<T> is implicitly convertible to T&.
>>>>> This allows you to do things like this:
>>>>>
>>>>>   void monitor_items() {
>>>>>     for (item const& i : watched_items) {
>>>>>       monitor(i);
>>>>>     }
>>>>>   }
>>>>>
>>>>> This could be generic code that operates on both containers of T and
>>>>> containers of view<T>.
>>>>>
>>>>
>>>> Generic in what way? Your generic code couldn't actually *do anything*
>>>> with the `view<T>`. Not directly. It could pass it to some other functions,
>>>> to be sure. But it could only pass it to ones which took the `view<T>`.
>>>> This function itself cannot access members of the object directly. It
>>>> couldn't send it to any function that took a `const T&`. And so forth.
>>>>
>>>> The only thing that would allow "generic code" to work as you suggest
>>>> is operator-dot.
>>>>
>>>
>>> I meant that the code could operate on both containers of T and
>>> containers of view<T>., because view<T> can be converted to T&. This
>>> was just a passing comment though; I wasn't trying to make a genuine case
>>> about view helping to write generic code. Incidentally though, could a
>>> proper "smart reference" which overloaded operator dot be used here? My
>>> understanding was that operator= would apply to the wrapped object
>>> (unless it were implemented in the wrapper, which would break its ref-like
>>> behaviour), so the reference itself wouldn't be copy assignable, which
>>> would prohibit storing it in a std::vector. Genuine question.
>>>
>>
>> With operator-dot, attempting to call `operator=(const smart_ref<T>&)`
>> would apply to the smart reference. Attempts to use `operator=(const T&)`
>> would be forwarded to `T`. So smart references could be copy-assignable if
>> you want, without breaking the ability to treat them as references.
>>
>
> Really? In that case, they can be stored in containers, but they don't
> really behave 100% like references.
>
>   int a = 0;
>   int b = 0;
>
>   int& ra = a;
>   int& rb = b;
>
>   ra = rb; // copies referenced value
>
>   smart_ref<int> sra = a;
>   smart_ref<int> srb = b;
>
>   sra = srb; // rebinds reference
>
> I thought the proposal suggested using a special "rebind" function so that
> smart references behave exactly like regular references?
>

And if you want your smart references to work that way, simply declare the
assignment operator `= delete`. But the operator-dot proposal doesn't exist
to tell you what to do with your types; it tells you what you *can do* with
them.

The proposal for operator-dot defines a mechanism, not a policy on how you
build smart references. I imagine that many of them will `=delete` the
operator; maybe all of them. But that is not a question for the
`operator-dot` proposal; it's a question for proposals for actual smart
reference types.

--
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/b8201a64-2101-48e3-b625-df547609ed99%40isocpp.org.

------=_Part_227_384558825.1476297066079
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, October 12, 2016 at 11:47:21 AM UTC-4, josep=
h....@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Wednesday, 12 October 2016 21:43:24 UTC+8, Nicol Bolas  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">On Wednesday, Octob=
er 12, 2016 at 3:07:15 AM UTC-4, <a>joseph....@gmail.com</a> wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, 12 October 2=
016 14:17:19 UTC+8, Nicol Bolas  wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div>On Tuesday, October 11, 2016 at 11:54:27 PM UTC-4, <a>joseph....@g=
mail.com</a> wrote:<br></div></blockquote><blockquote class=3D"gmail_quote"=
 style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D=
"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin=
-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><=
div>Let me rephrase that bit at the end.<br><br>`view&lt;int&gt;` and `not_=
null&lt;int*&gt;` have almost exactly the same interface. The <i>only diffe=
rence</i> between them is that one takes references and the other takes poi=
nters.<br><br>That trivial difference is not worth creating a whole new typ=
e for.</div></div></blockquote><div>=C2=A0<br>As I hope I&#39;ve demonstrat=
ed, taking a pointer makes run time errors into compile time errors and pus=
hes those errors up the call stack.</div></div></blockquote><div><br>That t=
hey push errors up the call stack is true, but just as with `not_null`, it =
only does so to the degree that the caller uses the type in question direct=
ly. What `view&lt;T&gt;` doesn&#39;t do is actually cause runtime checks fo=
r the error. So if you have a `T*`, and you don&#39;t check if it&#39;s NUL=
L, turning it into a `view&lt;T&gt;` is no less dangerous than turning it i=
nto a `not_null&lt;T*&gt;`. Indeed, it&#39;s more dangerous, since `not_nul=
l` will throw, while `view&lt;T&gt;` will have no idea that it has a NULL r=
eference.<br><br>I have yet to see an example where a runtime error becomes=
 a compile-time error as you suggest. This code is a potential runtime erro=
r:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px"><code><div><span style=3D=
"color:#008">void</span><span style=3D"color:#000"> foo</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">T </span><span style=3D"=
color:#660">*</span><span style=3D"color:#000">t</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>=C2=A0 not_null</span><span sty=
le=3D"color:#660">&lt;</span><span style=3D"color:#000">T</span><span style=
=3D"color:#660">*&gt;</span><span style=3D"color:#000"> nnt </span><span st=
yle=3D"color:#660">=3D</span><span style=3D"color:#000"> t</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">}</span></div></code></div><br></div></div></blockquote><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"><div>Show me the equi=
valent `view&lt;T&gt;` code that makes this a compile-time error. But <i>on=
ly when `t` is NULL</i>. That is, this code should compile fine for any use=
r who calls `foo` with a not-NULL pointer. But should fail to compile when =
`foo` is called with `nullptr`. That&#39;s what making &quot;run time error=
s into compile time errors&quot; would be; after all, the above code only i=
ssues a runtime error if you <i>actually call it</i> with NULL.<br><br>If t=
he compile-time version can&#39;t compile-time check the pointer&#39;s valu=
e, then it&#39;s not doing the same work. And therefore, it is not equivale=
nt code; it&#39;d an apples-to-oranges comparison.<br></div></div></blockqu=
ote><div><br>What I mean is that the API of <span style=3D"font-family:cour=
ier new,monospace">not_null</span> allows for run time errors, while the AP=
I of <span style=3D"font-family:courier new,monospace">view</span> doesn&#3=
9;t. If you want zero-overhead code, it is desirable to eliminate run time =
error checking. When I say it turns a run time error into a compile time er=
ror, I mean it does that by pushing the error up the stack.</div></div></bl=
ockquote><div><br>Yes. And by doing so, it has pushed it up the stack to th=
e point where it doesn&#39;t actually <i>check</i> the error. If the user h=
as a pointer, and they want to use `view`, it is *the user* who has to test=
 if it isn&#39;t NULL. Whereas `not_null` does the check automatically.<br>=
<br>So the above code is safer than this:<br><br><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px"><code><div><span style=3D"color:#008">void</span><span style=
=3D"color:#000"> foo</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">T </span><span style=3D"color:#660">*</span><span style=3D"=
color:#000">t</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>=C2=A0 view</span><span style=3D"color:#660">&lt;</span><span styl=
e=3D"color:#000">T</span><span style=3D"color:#660">&gt;</span><span style=
=3D"color:#000"> vt </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">*</span><span style=3D"c=
olor:#000">t</span><span style=3D"color:#660">;</span><span style=3D"color:=
#000"> </span><span style=3D"color:#800">//If null, UB, but nobody checks.<=
/span><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br></span></div></code></div><br>Pushing er=
rors &quot;up the stack&quot; is only a good thing if you actually check fo=
r them.<br></div></div></blockquote><div><br>That&#39;s my point: it&#39;s =
the user&#39;s responsibility to check that the pointer isn&#39;t null befo=
re dereferencing it. Sure, <span style=3D"font-family:courier new,monospace=
">not_null</span> turns potential UB into an exception, but at a performanc=
e cost (a run time check, and possible overhead relating to exceptions). By=
 using <span style=3D"font-family:courier new,monospace">not_null</span> in=
 our interface, we impose a performance cost (however small) on the user wh=
ether or not it&#39;s even possible for them to pass a null pointer. Using =
<span style=3D"font-family:courier new,monospace">view</span> (or a plain r=
eference) allows our interface to have zero run time overhead; we just have=
 to trust the user not to dereference any null pointers they may have hangi=
ng around. But ultimately, even if we use <span style=3D"font-family:courie=
r new,monospace">not_null</span>, the user can still dereference null point=
ers all day long. If we wanted to eliminate this possibility, we would be b=
etter off encouraging the use of an alternative to pointers which had no nu=
ll state -- perhaps something like <span style=3D"font-family:courier new,m=
onospace">view</span> :)<br></div></div></blockquote><div><br>I admit that =
`not_null&lt;T*&gt;` would be better if it could be constructed from a `T&a=
mp;`, which would also cause it to not bother checking if it is a null refe=
rence. And I have <a href=3D"https://github.com/Microsoft/GSL/issues/396">m=
ade such a suggestion</a>.<br><br>But regardless, I don&#39;t really unders=
tand what you&#39;re getting at here.<br><br>OK, you have some function tha=
t takes a pointer. And your function implicitly requires that this pointer =
not be NULL; therefore, it isn&#39;t going to check to see if it&#39;s NULL=
 or not. And you intend to store this not-null pointer around for a time an=
d use it later.<br><br>Then why do you not simply <i>store a pointer</i>? W=
hy do you need `view&lt;T&gt;` instead of `T*`? Your code already assumes i=
t&#39;s not NULL; what do you gain from using this type instead of `T*`? Th=
at you initialize it with `T&amp;` rather than `T*`? You still have to use =
`*` and `-&gt;` to access the `T`.<br><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><div> <br></div><blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div>I think this is important. I&#39;ve already listed one other reason:=
 semantics. view can convey meaning. As for other features, it really is ju=
st general syntactic niceness. The design of <span style=3D"font-family:cou=
rier new,monospace">view</span> and <span style=3D"font-family:courier new,=
monospace">optional_view</span> are still somewhat in flux, but I can think=
 of at least one other important feature.<br><br>I currently have it so tha=
t <span style=3D"font-family:courier new,monospace">view&lt;T&gt;</span> is=
 implicitly convertible to <span style=3D"font-family:courier new,monospace=
">T&amp;</span>. This allows you to do things like this:<br><br><span style=
=3D"font-family:courier new,monospace">=C2=A0 void monitor_items() {<br>=C2=
=A0=C2=A0=C2=A0 for (item const&amp; i : watched_items) {<br>=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 monitor(i);<br>=C2=A0=C2=A0=C2=A0 }<br>=C2=A0 }</span><b=
r><br>This could be generic code that operates on both containers of <span =
style=3D"font-family:courier new,monospace">T</span> and containers of <spa=
n style=3D"font-family:courier new,monospace">view&lt;T&gt;</span>.</div></=
div></blockquote><div><br>Generic in what way? Your generic code couldn&#39=
;t actually *do anything* with the `view&lt;T&gt;`. Not directly. It could =
pass it to some other functions, to be sure. But it could only pass it to o=
nes which took the `view&lt;T&gt;`. This function itself cannot access memb=
ers of the object directly. It couldn&#39;t send it to any function that to=
ok a `const T&amp;`. And so forth.<br><br>The only thing that would allow &=
quot;generic code&quot; to work as you suggest is operator-dot.<br></div></=
div></blockquote><div><br>I meant that the code could operate on both conta=
iners of <span style=3D"font-family:courier new,monospace">T</span> and con=
tainers of <span style=3D"font-family:courier new,monospace">view&lt;T&gt;<=
/span>., because <span style=3D"font-family:courier new,monospace">view&lt;=
T&gt;</span> can be converted to <span style=3D"font-family:courier new,mon=
ospace">T&amp;</span>. This was just a passing comment though; I wasn&#39;t=
 trying to make a genuine case about view helping to write generic code. In=
cidentally though, could a proper &quot;smart reference&quot; which overloa=
ded operator dot be used here? My understanding was that <span style=3D"fon=
t-family:courier new,monospace">operator=3D</span> would apply to the wrapp=
ed object (unless it were implemented in the wrapper, which would break its=
 ref-like behaviour), so the reference itself wouldn&#39;t be copy assignab=
le, which would prohibit storing it in a <span style=3D"font-family:courier=
 new,monospace">std::vector</span>. Genuine question.<br></div></div></bloc=
kquote><div><br>With operator-dot, attempting to call `operator=3D(const sm=
art_ref&lt;T&gt;&amp;)` would apply to the smart reference. Attempts to use=
 `operator=3D(const T&amp;)` would be forwarded to `T`. So smart references=
 could be copy-assignable if you want, without breaking the ability to trea=
t them as references.<br></div></div></blockquote><div><br>Really? In that =
case, they can be stored in containers, but they don&#39;t really behave 10=
0% like references.<br><br><span style=3D"font-family:courier new,monospace=
">=C2=A0 int a =3D 0;<br>=C2=A0 int b =3D 0;<br><br>=C2=A0 int&amp; ra =3D =
a;<br>=C2=A0 int&amp; rb =3D b;<br><br>=C2=A0 ra =3D rb; // copies referenc=
ed value<br><br>=C2=A0 smart_ref&lt;int&gt; sra =3D a;<br>=C2=A0 smart_ref&=
lt;int&gt; srb =3D b;<br><br>=C2=A0 sra =3D srb; // rebinds reference</span=
><br><br>I thought the proposal suggested using a special &quot;rebind&quot=
; function so that smart references behave exactly like regular references?=
<br></div></div></blockquote><div><br>And if you want your smart references=
 to work that way, simply declare the assignment operator `=3D delete`. But=
 the operator-dot proposal doesn&#39;t exist to tell you what to do with yo=
ur types; it tells you what you <i>can do</i> with them.<br><br>The proposa=
l for operator-dot defines a mechanism, not a policy on how you build smart=
 references. I imagine that many of them will `=3Ddelete` the operator; may=
be all of them. But that is not a question for the `operator-dot` proposal;=
 it&#39;s a question for proposals for actual smart reference types. <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/b8201a64-2101-48e3-b625-df547609ed99%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b8201a64-2101-48e3-b625-df547609ed99=
%40isocpp.org</a>.<br />

------=_Part_227_384558825.1476297066079--

------=_Part_226_2021079088.1476297066079--

.


Author: joseph.thomson@gmail.com
Date: Thu, 13 Oct 2016 01:27:50 -0700 (PDT)
Raw View
------=_Part_565_1228440570.1476347270919
Content-Type: multipart/alternative;
 boundary="----=_Part_566_433108405.1476347270919"

------=_Part_566_433108405.1476347270919
Content-Type: text/plain; charset=UTF-8

On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas wrote:

> That's my point: it's the user's responsibility to check that the pointer
>> isn't null before dereferencing it. Sure, not_null turns potential UB
>> into an exception, but at a performance cost (a run time check, and
>> possible overhead relating to exceptions). By using not_null in our
>> interface, we impose a performance cost (however small) on the user whether
>> or not it's even possible for them to pass a null pointer. Using view
>> (or a plain reference) allows our interface to have zero run time overhead;
>> we just have to trust the user not to dereference any null pointers they
>> may have hanging around. But ultimately, even if we use not_null, the
>> user can still dereference null pointers all day long. If we wanted to
>> eliminate this possibility, we would be better off encouraging the use of
>> an alternative to pointers which had no null state -- perhaps something
>> like view :)
>>
>
> I admit that `not_null<T*>` would be better if it could be constructed
> from a `T&`, which would also cause it to not bother checking if it is a
> null reference. And I have made such a suggestion
> <https://github.com/Microsoft/GSL/issues/396>.
>

While I like this from a compile-time safety perspective, I thought not_null
was meant to be more of a transparent wrapper. I'm not sure if modifying
the API of the wrapped type is within the scope of its design.

But regardless, I don't really understand what you're getting at here.
>
> OK, you have some function that takes a pointer. And your function
> implicitly requires that this pointer not be NULL; therefore, it isn't
> going to check to see if it's NULL or not. And you intend to store this
> not-null pointer around for a time and use it later.
>
> Then why do you not simply *store a pointer*? Why do you need `view<T>`
> instead of `T*`? Your code already assumes it's not NULL; what do you gain
> from using this type instead of `T*`? That you initialize it with `T&`
> rather than `T*`? You still have to use `*` and `->` to access the `T`.
>

Ideally, the function should not take a pointer if the pointer should not
be null, because it is unsafe (for code implementing the function) and
misleading (for the code calling the function). If the API can't be
changed, not_null is a great way to convey meaning and to add run-time
safety. If the API can be changed, the function should take a reference
instead, because then you have compile-time safety.

The problem with references is that they cannot be reassigned, which makes
them unusable in a lot of generic code (e.g. STL containers). As pointed
out, std::reference_wrapper exists for this purpose, but its API isn't
particularly nice to use as a general-purpose reference wrapper. In my
proposal, I intend view<T> and optional_view<T> to work in tandem as
replacements for T& and T* respectively wherever they represent
"references" (in the general sense). I tried to make the case for view<T>
having some semantic advantage over T&, but you've made me reconsider my
argument, since T& almost always means "reference" (in the general sense)
and T const& is almost always just to avoid an expensive copy. On the other
hand, optional_view<T> does convey additional meaning that T* does not,
since the meaning of T* is so horribly overloaded in C++. I think the case
for view is a lot stronger when it is accompanied by optional_view.

Why not store a pointer? Because it allows bugs to creep into your code.
Pointers can be null, and dereferencing a null pointer results in UB, and
UB is bad. Again, you could use not_null to catch any errors at run time,
but why catch an error at run time when it can be caught at compile time?
Sure, the safety of simple programs can be verified by eye, but not all
programs are simple. If "not-null" pointers are pervasive throughout a
complex system, the chance of null pointer bugs could be high.

Really? In that case, they can be stored in containers, but they don't
>>> really behave 100% like references.
>>>
>>>   int a = 0;
>>>   int b = 0;
>>>
>>>   int& ra = a;
>>>   int& rb = b;
>>>
>>>   ra = rb; // copies referenced value
>>>
>>>   smart_ref<int> sra = a;
>>>   smart_ref<int> srb = b;
>>>
>>>   sra = srb; // rebinds reference
>>>
>>> I thought the proposal suggested using a special "rebind" function so
>>> that smart references behave exactly like regular references?
>>>
>>
> And if you want your smart references to work that way, simply declare the
> assignment operator `= delete`. But the operator-dot proposal doesn't exist
> to tell you what to do with your types; it tells you what you *can do*
> with them.
>
> The proposal for operator-dot defines a mechanism, not a policy on how you
> build smart references. I imagine that many of them will `=delete` the
> operator; maybe all of them. But that is not a question for the
> `operator-dot` proposal; it's a question for proposals for actual smart
> reference types.
>

I appreciate the proposal doesn't specify the design of such types. Still,
I'm wondering what possible designs it would enable. If I understand
correctly, you could design two categories of "smart reference":

   1. operator=(ref<T> const&) modifies the wrapper
   2. operator=(ref<T> const&) modifies the wrapped object

The first option gives consistent behaviour when modifying the wrapper
(copy construct and copy assign do the same thing). However, it makes for
inconsistent behaviour when modifying the wrapper object. For example,
given smart references a and b:


  a.foo = y.foo; // modifies wrapped object
  a = b; // modifies wrapper

The second option gives consistent behaviour when modifying the wrapped
object, but has inconsistent behaviour when modifying the wrapper. This is
the behaviour of regular references that precludes them from being stored
in containers:

  ref<bar> a = b; // modifies (constructs) wrapper
  a = b; // modifies wrapped object

I'm sure the operator dot proposal will enable all sorts of great things
via run-time function overriding, but the quest for the perfect "smart
reference" design seems just out of reach. It seems this is because the
design of reference types is fundamentally different from the design of
value types in C++. Thus, view and optional_view do not use operator dot
overloading, because this seems to be the only way to get consistent
behaviour when modifying both the wrapper and when modifying the wrapped
object. You just have to use operator* and operator-> when working with the
underlying object.

--
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/68939a80-a8bc-424d-b01d-08435a5d5d7b%40isocpp.org.

------=_Part_566_433108405.1476347270919
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas  =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><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"><div>That&#39;s my po=
int: it&#39;s the user&#39;s responsibility to check that the pointer isn&#=
39;t null before dereferencing it. Sure, <span style=3D"font-family:courier=
 new,monospace">not_null</span> turns potential UB into an exception, but a=
t a performance cost (a run time check, and possible overhead relating to e=
xceptions). By using <span style=3D"font-family:courier new,monospace">not_=
null</span> in our interface, we impose a performance cost (however small) =
on the user whether or not it&#39;s even possible for them to pass a null p=
ointer. Using <span style=3D"font-family:courier new,monospace">view</span>=
 (or a plain reference) allows our interface to have zero run time overhead=
; we just have to trust the user not to dereference any null pointers they =
may have hanging around. But ultimately, even if we use <span style=3D"font=
-family:courier new,monospace">not_null</span>, the user can still derefere=
nce null pointers all day long. If we wanted to eliminate this possibility,=
 we would be better off encouraging the use of an alternative to pointers w=
hich had no null state -- perhaps something like <span style=3D"font-family=
:courier new,monospace">view</span> :)<br></div></div></blockquote><div><br=
>I admit that `not_null&lt;T*&gt;` would be better if it could be construct=
ed from a `T&amp;`, which would also cause it to not bother checking if it =
is a null reference. And I have <a href=3D"https://github.com/Microsoft/GSL=
/issues/396" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D=
&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FMicrosoft%2=
FGSL%2Fissues%2F396\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFkJLYOT7j2zWoXS=
KV0rlgtQbjIRA&#39;;return true;" onclick=3D"this.href=3D&#39;https://www.go=
ogle.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FMicrosoft%2FGSL%2Fissues%2F396=
\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFkJLYOT7j2zWoXSKV0rlgtQbjIRA&#39;;=
return true;">made such a suggestion</a>.<br></div></div></blockquote><div>=
<br>While I like this from a compile-time safety perspective, I thought <sp=
an style=3D"font-family: courier new,monospace;">not_null</span> was meant =
to be more of a transparent wrapper. I&#39;m not sure if modifying the API =
of the wrapped type is within the scope of its design.<br><br></div><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"><div>But regardless,=
 I don&#39;t really understand what you&#39;re getting at here.<br><br>OK, =
you have some function that takes a pointer. And your function implicitly r=
equires that this pointer not be NULL; therefore, it isn&#39;t going to che=
ck to see if it&#39;s NULL or not. And you intend to store this not-null po=
inter around for a time and use it later.<br><br>Then why do you not simply=
 <i>store a pointer</i>? Why do you need `view&lt;T&gt;` instead of `T*`? Y=
our code already assumes it&#39;s not NULL; what do you gain from using thi=
s type instead of `T*`? That you initialize it with `T&amp;` rather than `T=
*`? You still have to use `*` and `-&gt;` to access the `T`.<br></div></div=
></blockquote><br>Ideally, the function should not take a pointer if the po=
inter should not be null, because it is unsafe (for code implementing the f=
unction) and misleading (for the code calling the function). If the API can=
&#39;t be changed, <span style=3D"font-family: courier new,monospace;">not_=
null</span> is a great way to convey meaning and to add run-time safety. If=
 the API can be changed, the function should take a reference instead, beca=
use then you have compile-time safety.<br><br>The problem with references i=
s that they cannot be reassigned, which makes them unusable in a lot of gen=
eric code (e.g. STL containers). As pointed out, <span style=3D"font-family=
: courier new,monospace;">std::reference_wrapper</span> exists for this pur=
pose, but its API isn&#39;t particularly nice to use as a general-purpose r=
eference wrapper. In my proposal, I intend <span style=3D"font-family: cour=
ier new,monospace;">view&lt;T&gt;</span> and <span style=3D"font-family: co=
urier new,monospace;">optional_view</span>&lt;T&gt; to work in tandem as re=
placements for <span style=3D"font-family: courier new,monospace;">T&amp;</=
span> and <span style=3D"font-family: courier new,monospace;">T*</span> res=
pectively wherever they represent &quot;references&quot; (in the general se=
nse). I tried to make the case for <span style=3D"font-family: courier new,=
monospace;">view&lt;T&gt;</span> having some semantic advantage over <span =
style=3D"font-family: courier new,monospace;">T&amp;</span>, but you&#39;ve=
 made me reconsider my argument, since <span style=3D"font-family: courier =
new,monospace;">T&amp;</span> almost always means &quot;reference&quot; (in=
 the general sense) and <span style=3D"font-family: courier new,monospace;"=
>T const&amp;</span> is almost always just to avoid an expensive copy. On t=
he other hand, <span style=3D"font-family: courier new,monospace;">optional=
_view&lt;T&gt;</span> does convey additional meaning that <span style=3D"fo=
nt-family: courier new,monospace;">T*</span> does not, since the meaning of=
 <span style=3D"font-family: courier new,monospace;">T*</span> is so horrib=
ly overloaded in C++. I think the case for <span style=3D"font-family: cour=
ier new,monospace;">view</span> is a lot stronger when it is accompanied by=
 <span style=3D"font-family: courier new,monospace;">optional_view</span>.<=
br><br>Why not store a pointer? Because it allows bugs to creep into your c=
ode. Pointers can be null, and dereferencing a null pointer results in UB, =
and UB is bad. Again, you could use <span style=3D"font-family: courier new=
,monospace;">not_null</span> to catch any errors at run time, but why catch=
 an error at run time when it can be caught at compile time? Sure, the safe=
ty of simple programs can be verified by eye, but not all programs are simp=
le. If &quot;not-null&quot; pointers are pervasive throughout a complex sys=
tem, the chance of null pointer bugs could be high.<br><br><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><div>Really? In that case, they can be stored in containers, but =
they don&#39;t really behave 100% like references.<br><br><span style=3D"fo=
nt-family:courier new,monospace">=C2=A0 int a =3D 0;<br>=C2=A0 int b =3D 0;=
<br><br>=C2=A0 int&amp; ra =3D a;<br>=C2=A0 int&amp; rb =3D b;<br><br>=C2=
=A0 ra =3D rb; // copies referenced value<br><br>=C2=A0 smart_ref&lt;int&gt=
; sra =3D a;<br>=C2=A0 smart_ref&lt;int&gt; srb =3D b;<br><br>=C2=A0 sra =
=3D srb; // rebinds reference</span><br><br>I thought the proposal suggeste=
d using a special &quot;rebind&quot; function so that smart references beha=
ve exactly like regular references?<br></div></div></blockquote></div></blo=
ckquote><div><br>And if you want your smart references to work that way, si=
mply declare the assignment operator `=3D delete`. But the operator-dot pro=
posal doesn&#39;t exist to tell you what to do with your types; it tells yo=
u what you <i>can do</i> with them.<br><br>The proposal for operator-dot de=
fines a mechanism, not a policy on how you build smart references. I imagin=
e that many of them will `=3Ddelete` the operator; maybe all of them. But t=
hat is not a question for the `operator-dot` proposal; it&#39;s a question =
for proposals for actual smart reference types.<br></div></div></blockquote=
><div><br>I appreciate the proposal doesn&#39;t specify the design of such =
types. Still, I&#39;m wondering what possible designs it would enable. If I=
 understand correctly, you could design two categories of &quot;smart refer=
ence&quot;:<br><ol><li><span style=3D"font-family: courier new,monospace;">=
operator=3D(ref&lt;T&gt; const&amp;)</span> modifies the wrapper<br></li><l=
i><span style=3D"font-family: courier new,monospace;">operator=3D(ref&lt;T&=
gt; const&amp;)</span> modifies the wrapped object<br></li></ol><p>The firs=
t option gives consistent behaviour when modifying the wrapper (copy constr=
uct and copy assign do the same thing). However, it makes for inconsistent =
behaviour when modifying the wrapper object. For example, given smart refer=
ences <span style=3D"font-family: courier new,monospace;">a</span> and <spa=
n style=3D"font-family: courier new,monospace;">b</span>:<br></p><p><br></p=
><span style=3D"font-family: courier new,monospace;">=C2=A0 a.foo =3D y.foo=
; // modifies wrapped object<br>=C2=A0 a =3D b; // modifies wrapper</span><=
br><br>The second option gives consistent behaviour when modifying the wrap=
ped object, but has inconsistent behaviour when modifying the wrapper. This=
 is the behaviour of regular references that precludes them from being stor=
ed in containers:<br><br><span style=3D"font-family: courier new,monospace;=
">=C2=A0 ref&lt;bar&gt; a =3D b; // modifies (constructs) wrapper<br>=C2=A0=
 a =3D b; // modifies wrapped object<br></span><br>I&#39;m sure the operato=
r dot proposal will enable all sorts of great things via run-time function =
overriding, but the quest for the perfect &quot;smart reference&quot; desig=
n seems just out of reach. It seems this is because the design of reference=
 types is fundamentally different from the design of value types in C++. Th=
us, <span style=3D"font-family: courier new,monospace;">view</span> and <sp=
an style=3D"font-family: courier new,monospace;">optional_view</span> do no=
t use operator dot overloading, because this seems to be the only way to ge=
t consistent behaviour when modifying both the wrapper and when modifying t=
he wrapped object. You just have to use <span style=3D"font-family: courier=
 new,monospace;">operator*</span> and <span style=3D"font-family: courier n=
ew,monospace;">operator-&gt;</span> when working with the underlying object=
..<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/68939a80-a8bc-424d-b01d-08435a5d5d7b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/68939a80-a8bc-424d-b01d-08435a5d5d7b=
%40isocpp.org</a>.<br />

------=_Part_566_433108405.1476347270919--

------=_Part_565_1228440570.1476347270919--

.


Author: "D. B." <db0451@gmail.com>
Date: Thu, 13 Oct 2016 09:34:34 +0100
Raw View
--047d7bd91ac0bc418b053ebafa13
Content-Type: text/plain; charset=UTF-8

On Thu, Oct 13, 2016 at 9:27 AM, <joseph.thomson@gmail.com> wrote:

> I'm sure the operator dot proposal will enable all sorts of great things
> via run-time function overriding


But it's all about *compile-time* overloading.

--
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/CACGiwhEDQR_RUx676GTk-ySB24qXTo05OvN4cp_NGhECML%2B_ww%40mail.gmail.com.

--047d7bd91ac0bc418b053ebafa13
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Oct 13, 2016 at 9:27 AM,  <span dir=3D"ltr">&lt;<a href=3D"mailto:josep=
h.thomson@gmail.com" target=3D"_blank">joseph.thomson@gmail.com</a>&gt;</sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I&#39;m sur=
e the operator dot proposal will enable all sorts of great things via run-t=
ime function overriding</blockquote><div><br></div><div>But it&#39;s all ab=
out <i>compile-time</i> overloading. <br></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/CACGiwhEDQR_RUx676GTk-ySB24qXTo05OvN4=
cp_NGhECML%2B_ww%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CACGiwhEDQR_RUx=
676GTk-ySB24qXTo05OvN4cp_NGhECML%2B_ww%40mail.gmail.com</a>.<br />

--047d7bd91ac0bc418b053ebafa13--

.


Author: Victor Dyachenko <victor.dyachenko@gmail.com>
Date: Thu, 13 Oct 2016 01:50:44 -0700 (PDT)
Raw View
------=_Part_142_1584912742.1476348645024
Content-Type: multipart/alternative;
 boundary="----=_Part_143_934293752.1476348645024"

------=_Part_143_934293752.1476348645024
Content-Type: text/plain; charset=UTF-8

On Thursday, October 13, 2016 at 11:27:51 AM UTC+3, joseph....@gmail.com
wrote:
>
> Ideally, the function should not take a pointer if the pointer should not
> be null, because it is unsafe (for code implementing the function) and
> misleading (for the code calling the function). If the API can't be
> changed, not_null is a great way to convey meaning and to add run-time
> safety. If the API can be changed, the function should take a reference
> instead, because then you have compile-time safety.
>
Sadly, this rule seems non-obvious for people who add any_cast(any * ) and get_if(variant
* ) to the Standard right now...

--
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/ae1e672d-0e1d-4129-8b14-ffef65224ce9%40isocpp.org.

------=_Part_143_934293752.1476348645024
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, October 13, 2016 at 11:27:51 AM UTC+3, joseph=
.....@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">Ideally, the function should not take a pointer if the pointer sho=
uld not be null, because it is unsafe (for code implementing the function) =
and misleading (for the code calling the function). If the API can&#39;t be=
 changed, <span style=3D"font-family:courier new,monospace">not_null</span>=
 is a great way to convey meaning and to add run-time safety. If the API ca=
n be changed, the function should take a reference instead, because then yo=
u have compile-time safety.<br></div></blockquote><div>Sadly, this rule see=
ms non-obvious for people who add <span style=3D"font-family: courier new,m=
onospace;">any_cast(any * )</span> and <span style=3D"font-family: courier =
new,monospace;">get_if(variant * )</span> to the Standard right now...<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/ae1e672d-0e1d-4129-8b14-ffef65224ce9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ae1e672d-0e1d-4129-8b14-ffef65224ce9=
%40isocpp.org</a>.<br />

------=_Part_143_934293752.1476348645024--

------=_Part_142_1584912742.1476348645024--

.


Author: joseph.thomson@gmail.com
Date: Thu, 13 Oct 2016 02:12:59 -0700 (PDT)
Raw View
------=_Part_522_1543672886.1476349980022
Content-Type: multipart/alternative;
 boundary="----=_Part_523_268304444.1476349980022"

------=_Part_523_268304444.1476349980022
Content-Type: text/plain; charset=UTF-8

OnThursday, 13 October 2016 16:34:36 UTC+8, D. B. wrote:
>
> On Thu, Oct 13, 2016 at 9:27 AM, <joseph....@gmail.com <javascript:>>
> wrote:
>
>> I'm sure the operator dot proposal will enable all sorts of great things
>> via run-time function overriding
>
>
> But it's all about *compile-time* overloading.
>

 Suppose you could overload functions in the wrapped type as well, assuming
that is how overload resolution works with operator dot (I don't know the
details).

--
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/3f3ee0d8-6868-4595-b727-39a3a4e3b583%40isocpp.org.

------=_Part_523_268304444.1476349980022
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">OnThursday, 13 October 2016 16:34:36 UTC+8, D. B.  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"><div><div clas=
s=3D"gmail_quote">On Thu, Oct 13, 2016 at 9:27 AM,  <span dir=3D"ltr">&lt;<=
a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"nxC-56SeA=
QAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&#39;;retu=
rn true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true;">joseph=
.....@gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);pad=
ding-left:1ex">I&#39;m sure the operator dot proposal will enable all sorts=
 of great things via run-time function overriding</blockquote><div><br></di=
v><div>But it&#39;s all about <i>compile-time</i> overloading. <br></div></=
div></div></div></blockquote><div><br>=C2=A0Suppose you could overload func=
tions in the wrapped type as well, assuming that is how overload resolution=
 works with operator dot (I don&#39;t know the details).<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/3f3ee0d8-6868-4595-b727-39a3a4e3b583%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3f3ee0d8-6868-4595-b727-39a3a4e3b583=
%40isocpp.org</a>.<br />

------=_Part_523_268304444.1476349980022--

------=_Part_522_1543672886.1476349980022--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 13 Oct 2016 09:52:53 -0700 (PDT)
Raw View
------=_Part_466_367896232.1476377573217
Content-Type: multipart/alternative;
 boundary="----=_Part_467_1034610889.1476377573218"

------=_Part_467_1034610889.1476377573218
Content-Type: text/plain; charset=UTF-8

On Thursday, October 13, 2016 at 4:27:51 AM UTC-4, joseph....@gmail.com
wrote:
>
> On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas wrote:
>
>> That's my point: it's the user's responsibility to check that the pointer
>>> isn't null before dereferencing it. Sure, not_null turns potential UB
>>> into an exception, but at a performance cost (a run time check, and
>>> possible overhead relating to exceptions). By using not_null in our
>>> interface, we impose a performance cost (however small) on the user whether
>>> or not it's even possible for them to pass a null pointer. Using view
>>> (or a plain reference) allows our interface to have zero run time overhead;
>>> we just have to trust the user not to dereference any null pointers they
>>> may have hanging around. But ultimately, even if we use not_null, the
>>> user can still dereference null pointers all day long. If we wanted to
>>> eliminate this possibility, we would be better off encouraging the use of
>>> an alternative to pointers which had no null state -- perhaps something
>>> like view :)
>>>
>>
>> I admit that `not_null<T*>` would be better if it could be constructed
>> from a `T&`, which would also cause it to not bother checking if it is a
>> null reference. And I have made such a suggestion
>> <https://github.com/Microsoft/GSL/issues/396>.
>>
>
> While I like this from a compile-time safety perspective, I thought
> not_null was meant to be more of a transparent wrapper. I'm not sure if
> modifying the API of the wrapped type is within the scope of its design.
>

.... How does what I suggested modify the API of `T` itself?

But regardless, I don't really understand what you're getting at here.
>>
>> OK, you have some function that takes a pointer. And your function
>> implicitly requires that this pointer not be NULL; therefore, it isn't
>> going to check to see if it's NULL or not. And you intend to store this
>> not-null pointer around for a time and use it later.
>>
>> Then why do you not simply *store a pointer*? Why do you need `view<T>`
>> instead of `T*`? Your code already assumes it's not NULL; what do you gain
>> from using this type instead of `T*`? That you initialize it with `T&`
>> rather than `T*`? You still have to use `*` and `->` to access the `T`.
>>
>
> Ideally, the function should not take a pointer if the pointer should not
> be null, because it is unsafe (for code implementing the function) and
> misleading (for the code calling the function). If the API can't be changed,
> not_null is a great way to convey meaning and to add run-time safety.
>

In what way is adding `not_null` not a change to an API? At the very least,
it adds a user-defined conversion step, from `T*` to `not_null<T*>`. And
that can break code.

For example, many string classes have implicit conversions to `const char
*`. if you have a function that takes a `const char*`, you can pass one of
those string types to it. However, if that API changes to `not_null<const
char *>`, then you can't. That requires two user-defined conversion steps,
and C++ overload resolution doesn't let you do that.

And thus making such a change in the API broke your code. So turning `T*`
into `not_null<T*>` is not a safe change.


> If the API can be changed, the function should take a reference instead,
> because then you have compile-time safety.
>

No, you do not have "compile-time safety". What you *have* is
language-level assurance that, if the user somehow managed to pass a null
reference, then the user has *already* caused UB.

But the program as a whole has not been made any safer, either at compile
time or runtime. It simply makes the code more expressive of your intent
(since null references are UB). But so too does `not_null<T*>`.

If a user did this:

foo_not_null(get_a_pointer());

Where `foo_not_null` requires a non-NULL pointer, and `get_a_pointer` could
return NULL. This is runtime-safe. However, doing the following doesn't
become compile-time safe:

foo_view(*get_a_pointer());

Where `foo_view` takes a `view<T>`. No errors are being caught here, at
runtime or compile time. The user *must* check whether the pointer is NULL,
and the user failed to do so.

This program has less safety than the `not_null` version.

At the very least, `view<T>` should have a constructor that takes a `T*`
which throws if the pointer is NULL. Of course, if you did so, that would
make `view<T>` equivalent to my suggested fixed version of `not_null<T*>`.
So where is the advantage for `view<T>`?

The problem with references is that they cannot be reassigned, which makes
> them unusable in a lot of generic code (e.g. STL containers). As pointed
> out, std::reference_wrapper exists for this purpose, but its API isn't
> particularly nice to use as a general-purpose reference wrapper. In my
> proposal, I intend view<T> and optional_view<T> to work in tandem as
> replacements for T& and T* respectively wherever they represent
> "references" (in the general sense). I tried to make the case for view<T>
> having some semantic advantage over T&, but you've made me reconsider my
> argument, since T& almost always means "reference" (in the general sense)
> and T const& is almost always just to avoid an expensive copy. On the
> other hand, optional_view<T> does convey additional meaning that T* does
> not, since the meaning of T* is so horribly overloaded in C++.
>

In general, yes. But "in general" is talking about the reams of legacy code
that exists out there. That legacy code isn't going to switch from `T*` to
`optional_view<T>` no matter what.

The C++ core guidelines gives us a reasonably narrow field of usage of
naked pointers: they are nullable, non-owning references to a single `T`.
Exactly like your `optional_view<T>`.

So a user following good coding guidelines will use `T*` only for such
cases.

Though I suppose there is merit to the idea that if you're modernizing a
codebase, you need to distinguish between not-yet-modernized functions
where `T*` means "anything goes", and APIs that have been modernized where
`T*` means "nullable, non-owning references to a single `T`".

I think the case for view is a lot stronger when it is accompanied by
> optional_view.
>
> Why not store a pointer? Because it allows bugs to creep into your code.
> Pointers can be null, and dereferencing a null pointer results in UB, and
> UB is bad. Again, you could use not_null to catch any errors at run time,
> but why catch an error at run time when it can be caught at compile time?
> Sure, the safety of simple programs can be verified by eye, but not all
> programs are simple. If "not-null" pointers are pervasive throughout a
> complex system, the chance of null pointer bugs could be high.
>
> Really? In that case, they can be stored in containers, but they don't
>>>> really behave 100% like references.
>>>>
>>>>   int a = 0;
>>>>   int b = 0;
>>>>
>>>>   int& ra = a;
>>>>   int& rb = b;
>>>>
>>>>   ra = rb; // copies referenced value
>>>>
>>>>   smart_ref<int> sra = a;
>>>>   smart_ref<int> srb = b;
>>>>
>>>>   sra = srb; // rebinds reference
>>>>
>>>> I thought the proposal suggested using a special "rebind" function so
>>>> that smart references behave exactly like regular references?
>>>>
>>>
>> And if you want your smart references to work that way, simply declare
>> the assignment operator `= delete`. But the operator-dot proposal doesn't
>> exist to tell you what to do with your types; it tells you what you *can
>> do* with them.
>>
>> The proposal for operator-dot defines a mechanism, not a policy on how
>> you build smart references. I imagine that many of them will `=delete` the
>> operator; maybe all of them. But that is not a question for the
>> `operator-dot` proposal; it's a question for proposals for actual smart
>> reference types.
>>
>
> I appreciate the proposal doesn't specify the design of such types. Still,
> I'm wondering what possible designs it would enable. If I understand
> correctly, you could design two categories of "smart reference":
>
>    1. operator=(ref<T> const&) modifies the wrapper
>    2. operator=(ref<T> const&) modifies the wrapped object
>
> The first option gives consistent behaviour when modifying the wrapper
> (copy construct and copy assign do the same thing). However, it makes for
> inconsistent behaviour when modifying the wrapper object. For example,
> given smart references a and b:
>
>
>   a.foo = y.foo; // modifies wrapped object
>   a = b; // modifies wrapper
>
> The second option gives consistent behaviour when modifying the wrapped
> object, but has inconsistent behaviour when modifying the wrapper. This is
> the behaviour of regular references that precludes them from being stored
> in containers:
>

>
  ref<bar> a = b; // modifies (constructs) wrapper
>   a = b; // modifies wrapped object
>
>
I'm sure the operator dot proposal will enable all sorts of great things
> via run-time function overriding,
>

There's nothing "runtime" about operator-dot. Exactly what function gets
called when dealing with operator-dot types is well-defined at compile time.

but the quest for the perfect "smart reference" design seems just out of
> reach.
>

It is "out of reach" only because your definition of "perfect" is
inherently contradictory. You define "perfection" as emulating C++ language
references exactly, while simultaneously allowing by-reference copying via
operator=, which C++ language references do not do.

Emulating language references is a binary proposition. Either that's
something you want, or its something you don't.

It seems this is because the design of reference types is fundamentally
> different from the design of value types in C++. Thus, view and
> optional_view do not use operator dot overloading, because this seems to
> be the only way to get consistent behaviour when modifying both the wrapper
> and when modifying the wrapped object.
>

And yet, that's not true at all. Your option 1 above seems perfectly
consistent. Just like `a->foo == b->foo`. It only looks odd because you
expect `.` to mean "access the wrapper" instead of "possibly access the
wrapped object".

--
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/6990498c-47d3-4d1c-85c8-25f68a7fda86%40isocpp.org.

------=_Part_467_1034610889.1476377573218
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, October 13, 2016 at 4:27:51 AM UTC-4, joseph.=
....@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas  wrote:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div>That&#39;s my point: it&#39;s=
 the user&#39;s responsibility to check that the pointer isn&#39;t null bef=
ore dereferencing it. Sure, <span style=3D"font-family:courier new,monospac=
e">not_null</span> turns potential UB into an exception, but at a performan=
ce cost (a run time check, and possible overhead relating to exceptions). B=
y using <span style=3D"font-family:courier new,monospace">not_null</span> i=
n our interface, we impose a performance cost (however small) on the user w=
hether or not it&#39;s even possible for them to pass a null pointer. Using=
 <span style=3D"font-family:courier new,monospace">view</span> (or a plain =
reference) allows our interface to have zero run time overhead; we just hav=
e to trust the user not to dereference any null pointers they may have hang=
ing around. But ultimately, even if we use <span style=3D"font-family:couri=
er new,monospace">not_null</span>, the user can still dereference null poin=
ters all day long. If we wanted to eliminate this possibility, we would be =
better off encouraging the use of an alternative to pointers which had no n=
ull state -- perhaps something like <span style=3D"font-family:courier new,=
monospace">view</span> :)<br></div></div></blockquote><div><br>I admit that=
 `not_null&lt;T*&gt;` would be better if it could be constructed from a `T&=
amp;`, which would also cause it to not bother checking if it is a null ref=
erence. And I have <a href=3D"https://github.com/Microsoft/GSL/issues/396" =
rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D&#39;https://=
www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FMicrosoft%2FGSL%2Fissues=
%2F396\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFkJLYOT7j2zWoXSKV0rlgtQbjIRA=
&#39;;return true;" onclick=3D"this.href=3D&#39;https://www.google.com/url?=
q\x3dhttps%3A%2F%2Fgithub.com%2FMicrosoft%2FGSL%2Fissues%2F396\x26sa\x3dD\x=
26sntz\x3d1\x26usg\x3dAFQjCNFkJLYOT7j2zWoXSKV0rlgtQbjIRA&#39;;return true;"=
>made such a suggestion</a>.<br></div></div></blockquote><div><br>While I l=
ike this from a compile-time safety perspective, I thought <span style=3D"f=
ont-family:courier new,monospace">not_null</span> was meant to be more of a=
 transparent wrapper. I&#39;m not sure if modifying the API of the wrapped =
type is within the scope of its design.<br></div></div></blockquote><div><b=
r>... How does what I suggested modify the API of `T` itself?<br><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div>But regardless, I don&#39;=
t really understand what you&#39;re getting at here.<br><br>OK, you have so=
me function that takes a pointer. And your function implicitly requires tha=
t this pointer not be NULL; therefore, it isn&#39;t going to check to see i=
f it&#39;s NULL or not. And you intend to store this not-null pointer aroun=
d for a time and use it later.<br><br>Then why do you not simply <i>store a=
 pointer</i>? Why do you need `view&lt;T&gt;` instead of `T*`? Your code al=
ready assumes it&#39;s not NULL; what do you gain from using this type inst=
ead of `T*`? That you initialize it with `T&amp;` rather than `T*`? You sti=
ll have to use `*` and `-&gt;` to access the `T`.<br></div></div></blockquo=
te><br>Ideally, the function should not take a pointer if the pointer shoul=
d not be null, because it is unsafe (for code implementing the function) an=
d misleading (for the code calling the function). If the API can&#39;t be c=
hanged,<span style=3D"font-family:courier new,monospace"> not_null</span> i=
s a great way to convey meaning and to add run-time safety.</div></blockquo=
te><div><br>In what way is adding `not_null` not a change to an API? At the=
 very least, it adds a user-defined conversion step, from `T*` to `not_null=
&lt;T*&gt;`. And that can break code.<br><br>For example, many string class=
es have implicit conversions to `const char *`. if you have a function that=
 takes a `const char*`, you can pass one of those string types to it. Howev=
er, if that API changes to `not_null&lt;const char *&gt;`, then you can&#39=
;t. That requires two user-defined conversion steps, and C++ overload resol=
ution doesn&#39;t let you do that.<br><br>And thus making such a change in =
the API broke your code. So turning `T*` into `not_null&lt;T*&gt;` is not a=
 safe change.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr">If the API can be changed, the function should take a refer=
ence instead, because then you have compile-time safety.<br></div></blockqu=
ote><div><br>No, you do not have &quot;compile-time safety&quot;. What you =
<i>have</i> is language-level assurance that, if the user somehow managed t=
o pass a null reference, then the user has <i>already</i> caused UB.<br><br=
>But the program as a whole has not been made any safer, either at compile =
time or runtime. It simply makes the code more expressive of your intent (s=
ince null references are UB). But so too does `not_null&lt;T*&gt;`.<br><br>=
If a user did this:<br><br><div style=3D"background-color: rgb(250, 250, 25=
0); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1p=
x; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyp=
rint"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">foo_not_null</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">get_a_pointer</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">());</span></div></code></div><br>Where `foo_not_null` requi=
res a non-NULL pointer, and `get_a_pointer` could return NULL. This is runt=
ime-safe. However, doing the following doesn&#39;t become compile-time safe=
:<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"color: #000;" class=3D"styled-by-prettif=
y">foo_view</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">get_a_p=
ointer</span><span style=3D"color: #660;" class=3D"styled-by-prettify">());=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
></div></code></div><br>Where `foo_view` takes a `view&lt;T&gt;`. No errors=
 are being caught here, at runtime or compile time. The user <i>must</i> ch=
eck whether the pointer is NULL, and the user failed to do so.<br><br>This =
program has less safety than the `not_null` version.<br><br>At the very lea=
st, `view&lt;T&gt;` should have a constructor that takes a
 `T*` which throws if the pointer is NULL. Of course, if you did so, that w=
ould make `view&lt;T&gt;` equivalent to my suggested fixed version of `not_=
null&lt;T*&gt;`. So where is the advantage for `view&lt;T&gt;`?<br><br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">The problem=
 with references is that they cannot be reassigned, which makes them unusab=
le in a lot of generic code (e.g. STL containers). As pointed out, <span st=
yle=3D"font-family:courier new,monospace">std::reference_wrapper</span> exi=
sts for this purpose, but its API isn&#39;t particularly nice to use as a g=
eneral-purpose reference wrapper. In my proposal, I intend <span style=3D"f=
ont-family:courier new,monospace">view&lt;T&gt;</span> and <span style=3D"f=
ont-family:courier new,monospace">optional_view</span>&lt;T&gt; to work in =
tandem as replacements for <span style=3D"font-family:courier new,monospace=
">T&amp;</span> and <span style=3D"font-family:courier new,monospace">T*</s=
pan> respectively wherever they represent &quot;references&quot; (in the ge=
neral sense). I tried to make the case for <span style=3D"font-family:couri=
er new,monospace">view&lt;T&gt;</span> having some semantic advantage over =
<span style=3D"font-family:courier new,monospace">T&amp;</span>, but you&#3=
9;ve made me reconsider my argument, since <span style=3D"font-family:couri=
er new,monospace">T&amp;</span> almost always means &quot;reference&quot; (=
in the general sense) and <span style=3D"font-family:courier new,monospace"=
>T const&amp;</span> is almost always just to avoid an expensive copy. On t=
he other hand, <span style=3D"font-family:courier new,monospace">optional_v=
iew&lt;T&gt;</span> does convey additional meaning that <span style=3D"font=
-family:courier new,monospace">T*</span> does not, since the meaning of <sp=
an style=3D"font-family:courier new,monospace">T*</span> is so horribly ove=
rloaded in C++.</div></blockquote><div><br>In general, yes. But &quot;in ge=
neral&quot; is talking about the reams of legacy code that exists out there=
.. That legacy code isn&#39;t going to switch from `T*` to `optional_view&lt=
;T&gt;` no matter what.<br><br>The C++ core guidelines gives us a reasonabl=
y narrow field of usage of naked pointers: they are nullable, non-owning re=
ferences to a single `T`. Exactly like your `optional_view&lt;T&gt;`.<br><b=
r>So a user following good coding guidelines will use `T*` only for such ca=
ses.<br><br>Though I suppose there is merit to the idea that if you&#39;re =
modernizing a codebase, you need to distinguish between not-yet-modernized =
functions where `T*` means &quot;anything goes&quot;, and APIs that have be=
en modernized where `T*` means &quot;nullable, non-owning references to a s=
ingle `T`&quot;.<br><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div dir=3D"ltr">I think the case for <span style=3D"font-family:courier ne=
w,monospace">view</span> is a lot stronger when it is accompanied by <span =
style=3D"font-family:courier new,monospace">optional_view</span>.<br><br>Wh=
y not store a pointer? Because it allows bugs to creep into your code. Poin=
ters can be null, and dereferencing a null pointer results in UB, and UB is=
 bad. Again, you could use <span style=3D"font-family:courier new,monospace=
">not_null</span> to catch any errors at run time, but why catch an error a=
t run time when it can be caught at compile time? Sure, the safety of simpl=
e programs can be verified by eye, but not all programs are simple. If &quo=
t;not-null&quot; pointers are pervasive throughout a complex system, the ch=
ance of null pointer bugs could be high.<br><br><blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left=
:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>R=
eally? In that case, they can be stored in containers, but they don&#39;t r=
eally behave 100% like references.<br><br><span style=3D"font-family:courie=
r new,monospace">=C2=A0 int a =3D 0;<br>=C2=A0 int b =3D 0;<br><br>=C2=A0 i=
nt&amp; ra =3D a;<br>=C2=A0 int&amp; rb =3D b;<br><br>=C2=A0 ra =3D rb; // =
copies referenced value<br><br>=C2=A0 smart_ref&lt;int&gt; sra =3D a;<br>=
=C2=A0 smart_ref&lt;int&gt; srb =3D b;<br><br>=C2=A0 sra =3D srb; // rebind=
s reference</span><br><br>I thought the proposal suggested using a special =
&quot;rebind&quot; function so that smart references behave exactly like re=
gular references?<br></div></div></blockquote></div></blockquote><div><br>A=
nd if you want your smart references to work that way, simply declare the a=
ssignment operator `=3D delete`. But the operator-dot proposal doesn&#39;t =
exist to tell you what to do with your types; it tells you what you <i>can =
do</i> with them.<br><br>The proposal for operator-dot defines a mechanism,=
 not a policy on how you build smart references. I imagine that many of the=
m will `=3Ddelete` the operator; maybe all of them. But that is not a quest=
ion for the `operator-dot` proposal; it&#39;s a question for proposals for =
actual smart reference types.<br></div></div></blockquote><div><br>I apprec=
iate the proposal doesn&#39;t specify the design of such types. Still, I&#3=
9;m wondering what possible designs it would enable. If I understand correc=
tly, you could design two categories of &quot;smart reference&quot;:<br><ol=
><li><span style=3D"font-family:courier new,monospace">operator=3D(ref&lt;T=
&gt; const&amp;)</span> modifies the wrapper<br></li><li><span style=3D"fon=
t-family:courier new,monospace">operator=3D(ref&lt;T&gt; const&amp;)</span>=
 modifies the wrapped object<br></li></ol></div></div></blockquote><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><p>The first opt=
ion gives consistent behaviour when modifying the wrapper (copy construct a=
nd copy assign do the same thing). However, it makes for inconsistent behav=
iour when modifying the wrapper object. For example, given smart references=
 <span style=3D"font-family:courier new,monospace">a</span> and <span style=
=3D"font-family:courier new,monospace">b</span>:<br></p><p><br></p><span st=
yle=3D"font-family:courier new,monospace">=C2=A0 a.foo =3D y.foo; // modifi=
es wrapped object<br>=C2=A0 a =3D b; // modifies wrapper</span><br><br>The =
second option gives consistent behaviour when modifying the wrapped object,=
 but has inconsistent behaviour when modifying the wrapper. This is the beh=
aviour of regular references that precludes them from being stored in conta=
iners:<br></div></div></blockquote><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); p=
adding-left: 1ex;"><div>=C2=A0</div></blockquote><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><div><span style=3D"font-family:courier=
 new,monospace">=C2=A0 ref&lt;bar&gt; a =3D b; // modifies (constructs) wra=
pper<br>=C2=A0 a =3D b; // modifies wrapped object<br></span>=C2=A0</div></=
div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>I&#39;m sure the operator dot proposal will enable all sorts of gr=
eat things via run-time function overriding,</div></div></blockquote><div><=
br>There&#39;s nothing &quot;runtime&quot; about operator-dot. Exactly what=
 function gets called when dealing with operator-dot types is well-defined =
at compile time.<br><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div dir=3D"ltr"><div>but the quest for the perfect &quot;smart reference&q=
uot; design seems just out of reach.</div></div></blockquote><div><br>It is=
 &quot;out of reach&quot; only because your definition of &quot;perfect&quo=
t; is inherently contradictory. You define &quot;perfection&quot; as emulat=
ing C++ language references exactly, while simultaneously allowing by-refer=
ence copying via operator=3D, which C++ language references do not do.<br><=
br>Emulating language references is a binary proposition. Either that&#39;s=
 something you want, or its something you don&#39;t.<br><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>It seems this is =
because the design of reference types is fundamentally different from the d=
esign of value types in C++. Thus, <span style=3D"font-family:courier new,m=
onospace">view</span> and <span style=3D"font-family:courier new,monospace"=
>optional_view</span> do not use operator dot overloading, because this see=
ms to be the only way to get consistent behaviour when modifying both the w=
rapper and when modifying the wrapped object.</div></div></blockquote><div>=
<br>And yet, that&#39;s not true at all. Your option 1 above seems perfectl=
y consistent. Just like `a-&gt;foo =3D=3D b-&gt;foo`. It only looks odd bec=
ause you expect `.` to mean &quot;access the wrapper&quot; instead of &quot=
;possibly access the wrapped object&quot;.</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/6990498c-47d3-4d1c-85c8-25f68a7fda86%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6990498c-47d3-4d1c-85c8-25f68a7fda86=
%40isocpp.org</a>.<br />

------=_Part_467_1034610889.1476377573218--

------=_Part_466_367896232.1476377573217--

.


Author: joseph.thomson@gmail.com
Date: Fri, 14 Oct 2016 06:36:56 -0700 (PDT)
Raw View
------=_Part_1281_1807774262.1476452216445
Content-Type: multipart/alternative;
 boundary="----=_Part_1282_449887342.1476452216446"

------=_Part_1282_449887342.1476452216446
Content-Type: text/plain; charset=UTF-8

On Friday, 14 October 2016 00:52:53 UTC+8, Nicol Bolas wrote:
>
> On Thursday, October 13, 2016 at 4:27:51 AM UTC-4, joseph....@gmail.com
> wrote:
>>
>> On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas wrote:
>>
>>> That's my point: it's the user's responsibility to check that the
>>>> pointer isn't null before dereferencing it. Sure, not_null turns
>>>> potential UB into an exception, but at a performance cost (a run time
>>>> check, and possible overhead relating to exceptions). By using not_null
>>>> in our interface, we impose a performance cost (however small) on the user
>>>> whether or not it's even possible for them to pass a null pointer. Using
>>>> view (or a plain reference) allows our interface to have zero run time
>>>> overhead; we just have to trust the user not to dereference any null
>>>> pointers they may have hanging around. But ultimately, even if we use
>>>> not_null, the user can still dereference null pointers all day long.
>>>> If we wanted to eliminate this possibility, we would be better off
>>>> encouraging the use of an alternative to pointers which had no null state
>>>> -- perhaps something like view :)
>>>>
>>>
>>> I admit that `not_null<T*>` would be better if it could be constructed
>>> from a `T&`, which would also cause it to not bother checking if it is a
>>> null reference. And I have made such a suggestion
>>> <https://github.com/Microsoft/GSL/issues/396>.
>>>
>>
>> While I like this from a compile-time safety perspective, I thought
>> not_null was meant to be more of a transparent wrapper. I'm not sure if
>> modifying the API of the wrapped type is within the scope of its design.
>>
>
> ... How does what I suggested modify the API of `T` itself?
>
> But regardless, I don't really understand what you're getting at here.
>>>
>>> OK, you have some function that takes a pointer. And your function
>>> implicitly requires that this pointer not be NULL; therefore, it isn't
>>> going to check to see if it's NULL or not. And you intend to store this
>>> not-null pointer around for a time and use it later.
>>>
>>> Then why do you not simply *store a pointer*? Why do you need `view<T>`
>>> instead of `T*`? Your code already assumes it's not NULL; what do you gain
>>> from using this type instead of `T*`? That you initialize it with `T&`
>>> rather than `T*`? You still have to use `*` and `->` to access the `T`.
>>>
>>
>> Ideally, the function should not take a pointer if the pointer should not
>> be null, because it is unsafe (for code implementing the function) and
>> misleading (for the code calling the function). If the API can't be changed,
>> not_null is a great way to convey meaning and to add run-time safety.
>>
>
> In what way is adding `not_null` not a change to an API? At the very
> least, it adds a user-defined conversion step, from `T*` to `not_null<T*>`.
> And that can break code.
>
> For example, many string classes have implicit conversions to `const char
> *`. if you have a function that takes a `const char*`, you can pass one of
> those string types to it. However, if that API changes to `not_null<const
> char *>`, then you can't. That requires two user-defined conversion steps,
> and C++ overload resolution doesn't let you do that.
>
> And thus making such a change in the API broke your code. So turning `T*`
> into `not_null<T*>` is not a safe change.
>

I didn't mean to be taken so literally. A wrapper modifies the API of the
wrapped object insofar as it presents an alternative API to the user.
Anyway, I'm not in charge of the design of not_null; this was just an
observation based on my understanding.


> If the API can be changed, the function should take a reference instead,
>> because then you have compile-time safety.
>>
>
> No, you do not have "compile-time safety". What you *have* is
> language-level assurance that, if the user somehow managed to pass a null
> reference, then the user has *already* caused UB.
>
> But the program as a whole has not been made any safer, either at compile
> time or runtime. It simply makes the code more expressive of your intent
> (since null references are UB). But so too does `not_null<T*>`.
>
> If a user did this:
>
> foo_not_null(get_a_pointer());
>
> Where `foo_not_null` requires a non-NULL pointer, and `get_a_pointer`
> could return NULL. This is runtime-safe. However, doing the following
> doesn't become compile-time safe:
>
> foo_view(*get_a_pointer());
>
> Where `foo_view` takes a `view<T>`. No errors are being caught here, at
> runtime or compile time. The user *must* check whether the pointer is
> NULL, and the user failed to do so.
>
> This program has less safety than the `not_null` version.
>
> At the very least, `view<T>` should have a constructor that takes a `T*`
> which throws if the pointer is NULL. Of course, if you did so, that would
> make `view<T>` equivalent to my suggested fixed version of `not_null<T*>`.
> So where is the advantage for `view<T>`?
>

Okay, I understand your point. I guess my main problem is with potential
run-time cost where it isn't necessary.

However, I have just realized that the GSL allows the behaviour of contract
violations to be configured (it defaults to calling std::terminate). I
assume this is because we currently lack the static analysis tools that the
GSL is meant to assist. I am now assuming that the run-time check is
intended to be removed in release code (and if not_null were ever
standardized), in favour of static detection of unchecked pointer
dereferencing and conversion to not_null. This is supported by the
description in F.23
<https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-value>
of the C++ Core Guidelines.

If this were the case, not_null would not in fact be guaranteed to be "not
null" at run-time; the static analyzer would produce a warning of unchecked
conversion to not_null (though this check isn't specified in the C++ Core
Guidelines for some reason) and UB would arise potentially far from the
warning site, wherever the not_null wrapper were eventually dereferenced.
On the other hand, view *would* be guaranteed be "not null" at run-time;
the static analyzer would produce a warning of an unchecked dereference of
a raw pointer *at* the point at which UB arises. Another minor advantage is
that you don't need that extra check that I mentioned.

F.23 mentions that run-time checks can be performed in debug builds, but
most debuggers will catch a null pointer dereference, so I'm not sure how
useful this is.


> The problem with references is that they cannot be reassigned, which makes
>> them unusable in a lot of generic code (e.g. STL containers). As pointed
>> out, std::reference_wrapper exists for this purpose, but its API isn't
>> particularly nice to use as a general-purpose reference wrapper. In my
>> proposal, I intend view<T> and optional_view<T> to work in tandem as
>> replacements for T& and T* respectively wherever they represent
>> "references" (in the general sense). I tried to make the case for view<T>
>> having some semantic advantage over T&, but you've made me reconsider my
>> argument, since T& almost always means "reference" (in the general
>> sense) and T const& is almost always just to avoid an expensive copy. On
>> the other hand, optional_view<T> does convey additional meaning that T*
>> does not, since the meaning of T* is so horribly overloaded in C++.
>>
>
> In general, yes. But "in general" is talking about the reams of legacy
> code that exists out there. That legacy code isn't going to switch from
> `T*` to `optional_view<T>` no matter what.
>

I'm not entirely sure what you are responding to here, but I didn't intend
view or optional_view to be for legacy code in particular (unlike not_null,
which does appear to be geared towards improving the safety of legacy
code). They are intended to compliment existing standard library types with
a higher-level abstraction of the non-owning "reference" concept.


> The C++ core guidelines gives us a reasonably narrow field of usage of
> naked pointers: they are nullable, non-owning references to a single `T`.
> Exactly like your `optional_view<T>`.
>
> So a user following good coding guidelines will use `T*` only for such
> cases.
>
> Though I suppose there is merit to the idea that if you're modernizing a
> codebase, you need to distinguish between not-yet-modernized functions
> where `T*` means "anything goes", and APIs that have been modernized where
> `T*` means "nullable, non-owning references to a single `T`".
>

Not just modernizing an existing code base, but also writing new modern
code. Other features of view and optional_view are also nice, such as being
able to copy views, implicit conversion of view<T> to T& *and* T*,implicit
conversion from T* *and* T& (and view<T>) to optional_view<T>, a "safe
dereferencing" operation in optional_view::value, compatibility of view
with std::propagate_const, and the fact that both view and optional_view
have very similar APIs.

I think the case for view is a lot stronger when it is accompanied by
>> optional_view.
>>
>> Why not store a pointer? Because it allows bugs to creep into your code.
>> Pointers can be null, and dereferencing a null pointer results in UB, and
>> UB is bad. Again, you could use not_null to catch any errors at run
>> time, but why catch an error at run time when it can be caught at compile
>> time? Sure, the safety of simple programs can be verified by eye, but not
>> all programs are simple. If "not-null" pointers are pervasive throughout a
>> complex system, the chance of null pointer bugs could be high.
>>
>> Really? In that case, they can be stored in containers, but they don't
>>>>> really behave 100% like references.
>>>>>
>>>>>   int a = 0;
>>>>>   int b = 0;
>>>>>
>>>>>   int& ra = a;
>>>>>   int& rb = b;
>>>>>
>>>>>   ra = rb; // copies referenced value
>>>>>
>>>>>   smart_ref<int> sra = a;
>>>>>   smart_ref<int> srb = b;
>>>>>
>>>>>   sra = srb; // rebinds reference
>>>>>
>>>>> I thought the proposal suggested using a special "rebind" function so
>>>>> that smart references behave exactly like regular references?
>>>>>
>>>>
>>> And if you want your smart references to work that way, simply declare
>>> the assignment operator `= delete`. But the operator-dot proposal doesn't
>>> exist to tell you what to do with your types; it tells you what you *can
>>> do* with them.
>>>
>>> The proposal for operator-dot defines a mechanism, not a policy on how
>>> you build smart references. I imagine that many of them will `=delete` the
>>> operator; maybe all of them. But that is not a question for the
>>> `operator-dot` proposal; it's a question for proposals for actual smart
>>> reference types.
>>>
>>
>> I appreciate the proposal doesn't specify the design of such types.
>> Still, I'm wondering what possible designs it would enable. If I understand
>> correctly, you could design two categories of "smart reference":
>>
>>    1. operator=(ref<T> const&) modifies the wrapper
>>    2. operator=(ref<T> const&) modifies the wrapped object
>>
>> The first option gives consistent behaviour when modifying the wrapper
>> (copy construct and copy assign do the same thing). However, it makes for
>> inconsistent behaviour when modifying the wrapper object. For example,
>> given smart references a and b:
>>
>>
>>   a.foo = y.foo; // modifies wrapped object
>>   a = b; // modifies wrapper
>>
>> The second option gives consistent behaviour when modifying the wrapped
>> object, but has inconsistent behaviour when modifying the wrapper. This is
>> the behaviour of regular references that precludes them from being stored
>> in containers:
>>
>
>>
>   ref<bar> a = b; // modifies (constructs) wrapper
>>   a = b; // modifies wrapped object
>>
>>
> I'm sure the operator dot proposal will enable all sorts of great things
>> via run-time function overriding,
>>
>
> There's nothing "runtime" about operator-dot. Exactly what function gets
> called when dealing with operator-dot types is well-defined at compile time.
>

Sorry, that was a typo. I meant compile-time.


> but the quest for the perfect "smart reference" design seems just out of
>> reach.
>>
>
> It is "out of reach" only because your definition of "perfect" is
> inherently contradictory. You define "perfection" as emulating C++ language
> references exactly, while simultaneously allowing by-reference copying via
> operator=, which C++ language references do not do.
>
> Emulating language references is a binary proposition. Either that's
> something you want, or its something you don't.
>

I'm conflating C++ references and references in a general sense again. It
is possible to perfectly emulate C++ references (that would be my option
2). What I want (consistent behaviour for copying both wrapper and wrapped
objects) is out of reach when using operator dot overloading, so I don't
use it.


> It seems this is because the design of reference types is fundamentally
>> different from the design of value types in C++. Thus, view and
>> optional_view do not use operator dot overloading, because this seems to
>> be the only way to get consistent behaviour when modifying both the wrapper
>> and when modifying the wrapped object.
>>
>
> And yet, that's not true at all. Your option 1 above seems perfectly
> consistent. Just like `a->foo == b->foo`. It only looks odd because you
> expect `.` to mean "access the wrapper" instead of "possibly access the
> wrapped object".
>

When I say it isn't consistent, I mean that if a.foo = b.foo modifies the
wrapped object, then I expect a = b to modify the wrapped object as well.
The problem is that there is only one operator=, and two functions I want
it to perform. This is why I must, unfortunately, rely on operator* and
operator-> when referring to the wrapped object.

--
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/3ab79d96-c0a3-4960-a2ef-e88850d1b1c7%40isocpp.org.

------=_Part_1282_449887342.1476452216446
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, 14 October 2016 00:52:53 UTC+8, Nicol Bolas  wr=
ote:<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">On Thursd=
ay, October 13, 2016 at 4:27:51 AM UTC-4, <a>joseph....@gmail.com</a> 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">On Thursday, 13 O=
ctober 2016 02:31:06 UTC+8, Nicol Bolas  wrote:<br><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div>That&#39;s my point: it&#39;s the user&#39;s responsibi=
lity to check that the pointer isn&#39;t null before dereferencing it. Sure=
, <span style=3D"font-family:courier new,monospace">not_null</span> turns p=
otential UB into an exception, but at a performance cost (a run time check,=
 and possible overhead relating to exceptions). By using <span style=3D"fon=
t-family:courier new,monospace">not_null</span> in our interface, we impose=
 a performance cost (however small) on the user whether or not it&#39;s eve=
n possible for them to pass a null pointer. Using <span style=3D"font-famil=
y:courier new,monospace">view</span> (or a plain reference) allows our inte=
rface to have zero run time overhead; we just have to trust the user not to=
 dereference any null pointers they may have hanging around. But ultimately=
, even if we use <span style=3D"font-family:courier new,monospace">not_null=
</span>, the user can still dereference null pointers all day long. If we w=
anted to eliminate this possibility, we would be better off encouraging the=
 use of an alternative to pointers which had no null state -- perhaps somet=
hing like <span style=3D"font-family:courier new,monospace">view</span> :)<=
br></div></div></blockquote><div><br>I admit that `not_null&lt;T*&gt;` woul=
d be better if it could be constructed from a `T&amp;`, which would also ca=
use it to not bother checking if it is a null reference. And I have <a href=
=3D"https://github.com/Microsoft/GSL/issues/396" rel=3D"nofollow" target=3D=
"_blank" onmousedown=3D"this.href=3D&#39;https://www.google.com/url?q\x3dht=
tps%3A%2F%2Fgithub.com%2FMicrosoft%2FGSL%2Fissues%2F396\x26sa\x3dD\x26sntz\=
x3d1\x26usg\x3dAFQjCNFkJLYOT7j2zWoXSKV0rlgtQbjIRA&#39;;return true;" onclic=
k=3D"this.href=3D&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.=
com%2FMicrosoft%2FGSL%2Fissues%2F396\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQj=
CNFkJLYOT7j2zWoXSKV0rlgtQbjIRA&#39;;return true;">made such a suggestion</a=
>.<br></div></div></blockquote><div><br>While I like this from a compile-ti=
me safety perspective, I thought <span style=3D"font-family:courier new,mon=
ospace">not_null</span> was meant to be more of a transparent wrapper. I&#3=
9;m not sure if modifying the API of the wrapped type is within the scope o=
f its design.<br></div></div></blockquote><div><br>... How does what I sugg=
ested modify the API of `T` itself?<br><br></div><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"><blockquote class=3D"gmail_quote" style=3D"m=
argin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
 dir=3D"ltr"><div>But regardless, I don&#39;t really understand what you&#3=
9;re getting at here.<br><br>OK, you have some function that takes a pointe=
r. And your function implicitly requires that this pointer not be NULL; the=
refore, it isn&#39;t going to check to see if it&#39;s NULL or not. And you=
 intend to store this not-null pointer around for a time and use it later.<=
br><br>Then why do you not simply <i>store a pointer</i>? Why do you need `=
view&lt;T&gt;` instead of `T*`? Your code already assumes it&#39;s not NULL=
; what do you gain from using this type instead of `T*`? That you initializ=
e it with `T&amp;` rather than `T*`? You still have to use `*` and `-&gt;` =
to access the `T`.<br></div></div></blockquote><br>Ideally, the function sh=
ould not take a pointer if the pointer should not be null, because it is un=
safe (for code implementing the function) and misleading (for the code call=
ing the function). If the API can&#39;t be changed,<span style=3D"font-fami=
ly:courier new,monospace"> not_null</span> is a great way to convey meaning=
 and to add run-time safety.</div></blockquote><div><br>In what way is addi=
ng `not_null` not a change to an API? At the very least, it adds a user-def=
ined conversion step, from `T*` to `not_null&lt;T*&gt;`. And that can break=
 code.<br><br>For example, many string classes have implicit conversions to=
 `const char *`. if you have a function that takes a `const char*`, you can=
 pass one of those string types to it. However, if that API changes to `not=
_null&lt;const char *&gt;`, then you can&#39;t. That requires two user-defi=
ned conversion steps, and C++ overload resolution doesn&#39;t let you do th=
at.<br><br>And thus making such a change in the API broke your code. So tur=
ning `T*` into `not_null&lt;T*&gt;` is not a safe change.<br></div></div></=
blockquote><div><br>I didn&#39;t mean to be taken so literally. A wrapper m=
odifies the API of the wrapped object insofar as it presents an alternative=
 API to the user. Anyway, I&#39;m not in charge of the design of <span styl=
e=3D"font-family: courier new,monospace;">not_null</span>; this was just an=
 observation based on my understanding.<br>=C2=A0<br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr">If the API can be changed, the function should =
take a reference instead, because then you have compile-time safety.<br></d=
iv></blockquote><div><br>No, you do not have &quot;compile-time safety&quot=
;. What you <i>have</i> is language-level assurance that, if the user someh=
ow managed to pass a null reference, then the user has <i>already</i> cause=
d UB.<br><br>But the program as a whole has not been made any safer, either=
 at compile time or runtime. It simply makes the code more expressive of yo=
ur intent (since null references are UB). But so too does `not_null&lt;T*&g=
t;`.<br><br>If a user did this:<br><br><div style=3D"background-color:rgb(2=
50,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1=
px"><code><div><span style=3D"color:#000">foo_not_null</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">get_a_pointer</span><span s=
tyle=3D"color:#660">());</span></div></code></div><br>Where `foo_not_null` =
requires a non-NULL pointer, and `get_a_pointer` could return NULL. This is=
 runtime-safe. However, doing the following doesn&#39;t become compile-time=
 safe:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span styl=
e=3D"color:#000">foo_view</span><span style=3D"color:#660">(*</span><span s=
tyle=3D"color:#000">get_a_pointer</span><span style=3D"color:#660">());</sp=
an><span style=3D"color:#000"><br></span></div></code></div><br>Where `foo_=
view` takes a `view&lt;T&gt;`. No errors are being caught here, at runtime =
or compile time. The user <i>must</i> check whether the pointer is NULL, an=
d the user failed to do so.<br><br>This program has less safety than the `n=
ot_null` version.<br><br>At the very least, `view&lt;T&gt;` should have a c=
onstructor that takes a
 `T*` which throws if the pointer is NULL. Of course, if you did so, that w=
ould make `view&lt;T&gt;` equivalent to my suggested fixed version of `not_=
null&lt;T*&gt;`. So where is the advantage for `view&lt;T&gt;`?<br></div></=
div></blockquote><div><br>Okay, I understand your point. I guess my main pr=
oblem is with potential run-time cost where it isn&#39;t necessary.<br><br>=
However, I have just realized that the GSL allows the behaviour of contract=
 violations to be configured (it defaults to calling <span style=3D"font-fa=
mily: courier new,monospace;">std::terminate</span>). I assume this is beca=
use we currently lack the static analysis tools that the GSL is meant to as=
sist. I am now assuming that the run-time check is intended to be removed i=
n release code (and if <span style=3D"font-family: courier new,monospace;">=
not_null</span> were ever standardized), in favour of static detection of u=
nchecked pointer dereferencing and conversion to <span style=3D"font-family=
: courier new,monospace;">not_null</span>. This is supported by the descrip=
tion in <a href=3D"https://github.com/isocpp/CppCoreGuidelines/blob/master/=
CppCoreGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-val=
id-value">F.23</a> of the C++ Core Guidelines.<br><br>If this were the case=
, <span style=3D"font-family: courier new,monospace;">not_null</span> would=
 not in fact be guaranteed to be &quot;not null&quot; at run-time; the stat=
ic analyzer would produce a warning of unchecked conversion to <span style=
=3D"font-family: courier new,monospace;">not_null</span> (though this check=
 isn&#39;t specified in the C++ Core Guidelines for some reason) and UB wou=
ld arise potentially far from the warning site, wherever the <span style=3D=
"font-family: courier new,monospace;">not_null</span> wrapper were eventual=
ly dereferenced. On the other hand, <span style=3D"font-family: courier new=
,monospace;">view</span> <i>would</i> be guaranteed be &quot;not null&quot;=
 at run-time; the static analyzer would produce a warning of an unchecked d=
ereference of a raw pointer <i>at</i> the point at which UB arises. Another=
 minor advantage is that you don&#39;t need that extra check that I mention=
ed.<br><br>F.23 mentions that run-time checks can be performed in debug bui=
lds, but most debuggers will catch a null pointer dereference, so I&#39;m n=
ot sure how useful this is.<br>=C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr">The problem with references is that they cannot be r=
eassigned, which makes them unusable in a lot of generic code (e.g. STL con=
tainers). As pointed out, <span style=3D"font-family:courier new,monospace"=
>std::reference_wrapper</span> exists for this purpose, but its API isn&#39=
;t particularly nice to use as a general-purpose reference wrapper. In my p=
roposal, I intend <span style=3D"font-family:courier new,monospace">view&lt=
;T&gt;</span> and <span style=3D"font-family:courier new,monospace">optiona=
l_view</span>&lt;T&gt; to work in tandem as replacements for <span style=3D=
"font-family:courier new,monospace">T&amp;</span> and <span style=3D"font-f=
amily:courier new,monospace">T*</span> respectively wherever they represent=
 &quot;references&quot; (in the general sense). I tried to make the case fo=
r <span style=3D"font-family:courier new,monospace">view&lt;T&gt;</span> ha=
ving some semantic advantage over <span style=3D"font-family:courier new,mo=
nospace">T&amp;</span>, but you&#39;ve made me reconsider my argument, sinc=
e <span style=3D"font-family:courier new,monospace">T&amp;</span> almost al=
ways means &quot;reference&quot; (in the general sense) and <span style=3D"=
font-family:courier new,monospace">T const&amp;</span> is almost always jus=
t to avoid an expensive copy. On the other hand, <span style=3D"font-family=
:courier new,monospace">optional_view&lt;T&gt;</span> does convey additiona=
l meaning that <span style=3D"font-family:courier new,monospace">T*</span> =
does not, since the meaning of <span style=3D"font-family:courier new,monos=
pace">T*</span> is so horribly overloaded in C++.</div></blockquote><div><b=
r>In general, yes. But &quot;in general&quot; is talking about the reams of=
 legacy code that exists out there. That legacy code isn&#39;t going to swi=
tch from `T*` to `optional_view&lt;T&gt;` no matter what.<br></div></div></=
blockquote><div><br>I&#39;m not entirely sure what you are responding to he=
re, but I didn&#39;t intend <span style=3D"font-family: courier new,monospa=
ce;">view</span> or <span style=3D"font-family: courier new,monospace;">opt=
ional_view</span> to be for legacy code in particular (unlike not_null, whi=
ch does appear to be geared towards improving the safety of legacy code). T=
hey are intended to compliment existing standard library types with a highe=
r-level abstraction of the non-owning &quot;reference&quot; concept. <br>=
=C2=A0</div><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"><=
div>The C++ core guidelines gives us a reasonably narrow field of usage of =
naked pointers: they are nullable, non-owning references to a single `T`. E=
xactly like your `optional_view&lt;T&gt;`.<br><br>So a user following good =
coding guidelines will use `T*` only for such cases.<br><br>Though I suppos=
e there is merit to the idea that if you&#39;re modernizing a codebase, you=
 need to distinguish between not-yet-modernized functions where `T*` means =
&quot;anything goes&quot;, and APIs that have been modernized where `T*` me=
ans &quot;nullable, non-owning references to a single `T`&quot;.<br></div><=
/div></blockquote><div>=C2=A0<br>Not just modernizing an existing code base=
, but also writing new modern code. Other features of <span style=3D"font-f=
amily: courier new,monospace;">view</span> and <span style=3D"font-family: =
courier new,monospace;">optional_view</span> are also nice, such as being a=
ble to copy <span style=3D"font-family: courier new,monospace;">view<span s=
tyle=3D"font-family: arial,sans-serif;">s</span></span>, implicit conversio=
n of <span style=3D"font-family: courier new,monospace;">view&lt;T&gt;</spa=
n> to <span style=3D"font-family: courier new,monospace;">T&amp;</span> <i>=
and</i> <span style=3D"font-family: courier new,monospace;">T*</span><span =
style=3D"font-family: courier new,monospace;"></span>,implicit conversion f=
rom <span style=3D"font-family: courier new,monospace;">T*</span> <i>and</i=
> <span style=3D"font-family: courier new,monospace;">T&amp;</span> (and <s=
pan style=3D"font-family: courier new,monospace;">view&lt;T&gt;</span>) to =
<span style=3D"font-family: courier new,monospace;">optional_view&lt;T&gt;<=
/span>, a &quot;safe dereferencing&quot; operation in <span style=3D"font-f=
amily: courier new,monospace;">optional_view::value</span>, compatibility o=
f <span style=3D"font-family: courier new,monospace;">view</span> with <spa=
n style=3D"font-family: courier new,monospace;">std::propagate_const</span>=
, and the fact that both <span style=3D"font-family: courier new,monospace;=
">view</span> and <span style=3D"font-family: courier new,monospace;">optio=
nal_view</span> have very similar APIs.<br><br></div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr">I think the case for <span style=3D"font-f=
amily:courier new,monospace">view</span> is a lot stronger when it is accom=
panied by <span style=3D"font-family:courier new,monospace">optional_view</=
span>.<br><br>Why not store a pointer? Because it allows bugs to creep into=
 your code. Pointers can be null, and dereferencing a null pointer results =
in UB, and UB is bad. Again, you could use <span style=3D"font-family:couri=
er new,monospace">not_null</span> to catch any errors at run time, but why =
catch an error at run time when it can be caught at compile time? Sure, the=
 safety of simple programs can be verified by eye, but not all programs are=
 simple. If &quot;not-null&quot; pointers are pervasive throughout a comple=
x system, the chance of null pointer bugs could be high.<br><br><blockquote=
 class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><div>Really? In that case, they can be stored in containers, but =
they don&#39;t really behave 100% like references.<br><br><span style=3D"fo=
nt-family:courier new,monospace">=C2=A0 int a =3D 0;<br>=C2=A0 int b =3D 0;=
<br><br>=C2=A0 int&amp; ra =3D a;<br>=C2=A0 int&amp; rb =3D b;<br><br>=C2=
=A0 ra =3D rb; // copies referenced value<br><br>=C2=A0 smart_ref&lt;int&gt=
; sra =3D a;<br>=C2=A0 smart_ref&lt;int&gt; srb =3D b;<br><br>=C2=A0 sra =
=3D srb; // rebinds reference</span><br><br>I thought the proposal suggeste=
d using a special &quot;rebind&quot; function so that smart references beha=
ve exactly like regular references?<br></div></div></blockquote></div></blo=
ckquote><div><br>And if you want your smart references to work that way, si=
mply declare the assignment operator `=3D delete`. But the operator-dot pro=
posal doesn&#39;t exist to tell you what to do with your types; it tells yo=
u what you <i>can do</i> with them.<br><br>The proposal for operator-dot de=
fines a mechanism, not a policy on how you build smart references. I imagin=
e that many of them will `=3Ddelete` the operator; maybe all of them. But t=
hat is not a question for the `operator-dot` proposal; it&#39;s a question =
for proposals for actual smart reference types.<br></div></div></blockquote=
><div><br>I appreciate the proposal doesn&#39;t specify the design of such =
types. Still, I&#39;m wondering what possible designs it would enable. If I=
 understand correctly, you could design two categories of &quot;smart refer=
ence&quot;:<br><ol><li><span style=3D"font-family:courier new,monospace">op=
erator=3D(ref&lt;T&gt; const&amp;)</span> modifies the wrapper<br></li><li>=
<span style=3D"font-family:courier new,monospace">operator=3D(ref&lt;T&gt; =
const&amp;)</span> modifies the wrapped object<br></li></ol></div></div></b=
lockquote><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><p>=
The first option gives consistent behaviour when modifying the wrapper (cop=
y construct and copy assign do the same thing). However, it makes for incon=
sistent behaviour when modifying the wrapper object. For example, given sma=
rt references <span style=3D"font-family:courier new,monospace">a</span> an=
d <span style=3D"font-family:courier new,monospace">b</span>:<br></p><p><br=
></p><span style=3D"font-family:courier new,monospace">=C2=A0 a.foo =3D y.f=
oo; // modifies wrapped object<br>=C2=A0 a =3D b; // modifies wrapper</span=
><br><br>The second option gives consistent behaviour when modifying the wr=
apped object, but has inconsistent behaviour when modifying the wrapper. Th=
is is the behaviour of regular references that precludes them from being st=
ored in containers:<br></div></div></blockquote><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>=C2=A0</div></blockquote><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><div><span style=3D"font-family:courier =
new,monospace">=C2=A0 ref&lt;bar&gt; a =3D b; // modifies (constructs) wrap=
per<br>=C2=A0 a =3D b; // modifies wrapped object<br></span>=C2=A0</div></d=
iv></blockquote><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"><d=
iv>I&#39;m sure the operator dot proposal will enable all sorts of great th=
ings via run-time function overriding,</div></div></blockquote><div><br>The=
re&#39;s nothing &quot;runtime&quot; about operator-dot. Exactly what funct=
ion gets called when dealing with operator-dot types is well-defined at com=
pile time.<br></div></div></blockquote><div><br>Sorry, that was a typo. I m=
eant compile-time.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div>but the quest for the perfect &quot;smart reference&=
quot; design seems just out of reach.</div></div></blockquote><div><br>It i=
s &quot;out of reach&quot; only because your definition of &quot;perfect&qu=
ot; is inherently contradictory. You define &quot;perfection&quot; as emula=
ting C++ language references exactly, while simultaneously allowing by-refe=
rence copying via operator=3D, which C++ language references do not do.<br>=
<br>Emulating language references is a binary proposition. Either that&#39;=
s something you want, or its something you don&#39;t.<br></div></div></bloc=
kquote><div><br>I&#39;m conflating C++ references and references in a gener=
al sense again. It is possible to perfectly emulate C++ references (that wo=
uld be my option 2). What I want (consistent behaviour for copying both wra=
pper and wrapped objects) is out of reach when using operator dot overloadi=
ng, so I don&#39;t use it.<span style=3D"font-family: courier new,monospace=
;"></span><br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
 dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D=
"ltr"><div>It seems this is because the design of reference types is fundam=
entally different from the design of value types in C++. Thus, <span style=
=3D"font-family:courier new,monospace">view</span> and <span style=3D"font-=
family:courier new,monospace">optional_view</span> do not use operator dot =
overloading, because this seems to be the only way to get consistent behavi=
our when modifying both the wrapper and when modifying the wrapped object.<=
/div></div></blockquote><div><br>And yet, that&#39;s not true at all. Your =
option 1 above seems perfectly consistent. Just like `a-&gt;foo =3D=3D b-&g=
t;foo`. It only looks odd because you expect `.` to mean &quot;access the w=
rapper&quot; instead of &quot;possibly access the wrapped object&quot;.</di=
v></div></blockquote><div><br>When I say it isn&#39;t consistent, I mean th=
at if <span style=3D"font-family: courier new,monospace;">a.foo =3D b.foo</=
span> modifies the wrapped object, then I expect <span style=3D"font-family=
: courier new,monospace;">a =3D b</span> to modify the wrapped object as we=
ll. The problem is that there is only one <span style=3D"font-family: couri=
er new,monospace;">operator=3D</span>, and two functions I want it to perfo=
rm. This is why I must, unfortunately, rely on <span style=3D"font-family: =
courier new,monospace;">operator*</span> and <span style=3D"font-family: co=
urier new,monospace;">operator-&gt;</span> when referring to the wrapped ob=
ject.<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/3ab79d96-c0a3-4960-a2ef-e88850d1b1c7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3ab79d96-c0a3-4960-a2ef-e88850d1b1c7=
%40isocpp.org</a>.<br />

------=_Part_1282_449887342.1476452216446--

------=_Part_1281_1807774262.1476452216445--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 14 Oct 2016 08:23:15 -0700 (PDT)
Raw View
------=_Part_1014_824200238.1476458595239
Content-Type: multipart/alternative;
 boundary="----=_Part_1015_770977443.1476458595239"

------=_Part_1015_770977443.1476458595239
Content-Type: text/plain; charset=UTF-8

On Friday, October 14, 2016 at 9:36:56 AM UTC-4, joseph....@gmail.com wrote:
>
> On Friday, 14 October 2016 00:52:53 UTC+8, Nicol Bolas wrote:
>>
>> On Thursday, October 13, 2016 at 4:27:51 AM UTC-4, joseph....@gmail.com
>> wrote:
>>>
>>> On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas wrote:
>>>
>>
>> No, you do not have "compile-time safety". What you *have* is
>> language-level assurance that, if the user somehow managed to pass a null
>> reference, then the user has *already* caused UB.
>>
>> But the program as a whole has not been made any safer, either at compile
>> time or runtime. It simply makes the code more expressive of your intent
>> (since null references are UB). But so too does `not_null<T*>`.
>>
>> If a user did this:
>>
>> foo_not_null(get_a_pointer());
>>
>> Where `foo_not_null` requires a non-NULL pointer, and `get_a_pointer`
>> could return NULL. This is runtime-safe. However, doing the following
>> doesn't become compile-time safe:
>>
>> foo_view(*get_a_pointer());
>>
>> Where `foo_view` takes a `view<T>`. No errors are being caught here, at
>> runtime or compile time. The user *must* check whether the pointer is
>> NULL, and the user failed to do so.
>>
>> This program has less safety than the `not_null` version.
>>
>> At the very least, `view<T>` should have a constructor that takes a `T*`
>> which throws if the pointer is NULL. Of course, if you did so, that would
>> make `view<T>` equivalent to my suggested fixed version of `not_null<T*>`.
>> So where is the advantage for `view<T>`?
>>
>
> Okay, I understand your point. I guess my main problem is with potential
> run-time cost where it isn't necessary.
>

Which, if my change for `not_null` goes through, can be easily mitigated.
The cost only happens when the pointer is introduced to `not_null`. If you
pass a reference, there's no check.


> However, I have just realized that the GSL allows the behaviour of
> contract violations to be configured (it defaults to calling
> std::terminate). I assume this is because we currently lack the static
> analysis tools that the GSL is meant to assist. I am now assuming that the
> run-time check is intended to be removed in release code (and if not_null
> were ever standardized), in favour of static detection of unchecked pointer
> dereferencing and conversion to not_null. This is supported by the
> description in F.23
> <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-value>
> of the C++ Core Guidelines.
>
> If this were the case, not_null would not in fact be guaranteed to be
> "not null" at run-time; the static analyzer would produce a warning of
> unchecked conversion to not_null (though this check isn't specified in
> the C++ Core Guidelines for some reason) and UB would arise potentially far
> from the warning site, wherever the not_null wrapper were eventually
> dereferenced. On the other hand, view *would* be guaranteed be "not null"
> at run-time; the static analyzer would produce a warning of an unchecked
> dereference of a raw pointer *at* the point at which UB arises. Another
> minor advantage is that you don't need that extra check that I mentioned.
>
> F.23 mentions that run-time checks can be performed in debug builds, but
> most debuggers will catch a null pointer dereference, so I'm not sure how
> useful this is.
>

It's very useful. A debugger can detect a NULL pointer dereference, but
only at the cite of use, not the place where the NULL pointer *came from*.
If the code that stored the pointer had used `not_null`, then they could
get an error at the source of the pointer. Or at least, at the edges of the
system that expected it to not be NULL, rather than wherever it first got
used.

The problem with references is that they cannot be reassigned, which makes
>>> them unusable in a lot of generic code (e.g. STL containers). As pointed
>>> out, std::reference_wrapper exists for this purpose, but its API isn't
>>> particularly nice to use as a general-purpose reference wrapper. In my
>>> proposal, I intend view<T> and optional_view<T> to work in tandem as
>>> replacements for T& and T* respectively wherever they represent
>>> "references" (in the general sense). I tried to make the case for
>>> view<T> having some semantic advantage over T&, but you've made me
>>> reconsider my argument, since T& almost always means "reference" (in
>>> the general sense) and T const& is almost always just to avoid an
>>> expensive copy. On the other hand, optional_view<T> does convey
>>> additional meaning that T* does not, since the meaning of T* is so
>>> horribly overloaded in C++.
>>>
>>
>> In general, yes. But "in general" is talking about the reams of legacy
>> code that exists out there. That legacy code isn't going to switch from
>> `T*` to `optional_view<T>` no matter what.
>>
>
> I'm not entirely sure what you are responding to here, but I didn't intend
> view or optional_view to be for legacy code in particular (unlike
> not_null, which does appear to be geared towards improving the safety of
> legacy code). They are intended to compliment existing standard library
> types with a higher-level abstraction of the non-owning "reference" concept.
>

What I'm getting at is that, in code written for modern C++, it is
reasonable to assume that `T*` has a specific meaning: nullable, non-owning
reference to a single object. So if you're writing modern C++, you don't
need `optional_view<T>` to say what the much shorter `T*` already says.

So `optional_view<T>` is only advantageous when working with a codebase
where `T*` does not consistently have a specific meaning. Hopefully, we're
not writing more of that kind of code...

but the quest for the perfect "smart reference" design seems just out of
>>> reach.
>>>
>>
>> It is "out of reach" only because your definition of "perfect" is
>> inherently contradictory. You define "perfection" as emulating C++ language
>> references exactly, while simultaneously allowing by-reference copying via
>> operator=, which C++ language references do not do.
>>
>> Emulating language references is a binary proposition. Either that's
>> something you want, or its something you don't.
>>
>
> I'm conflating C++ references and references in a general sense again. It
> is possible to perfectly emulate C++ references (that would be my option
> 2). What I want (consistent behaviour for copying both wrapper and wrapped
> objects) is out of reach when using operator dot overloading, so I don't
> use it.
>
>
>> It seems this is because the design of reference types is fundamentally
>>> different from the design of value types in C++. Thus, view and
>>> optional_view do not use operator dot overloading, because this seems
>>> to be the only way to get consistent behaviour when modifying both the
>>> wrapper and when modifying the wrapped object.
>>>
>>
>> And yet, that's not true at all. Your option 1 above seems perfectly
>> consistent. Just like `a->foo == b->foo`. It only looks odd because you
>> expect `.` to mean "access the wrapper" instead of "possibly access the
>> wrapped object".
>>
>
> When I say it isn't consistent, I mean that if a.foo = b.foo modifies the
> wrapped object, then I expect a = b to modify the wrapped object as well.
> The problem is that there is only one operator=, and two functions I want
> it to perform. This is why I must, unfortunately, rely on operator* and
> operator-> when referring to the wrapped object.
>

So... why is it consistent for `a->foo = b->foo` to have different behavior
from `a = b`, yet `a.foo = b.foo` should have the same behavior?

The answer is simple: because you expect `->` to mean "access wrapped
object", while you expect `.` to mean "access handle". You live in a world
sans-operator-dot, so you don't expect `a.foo` to potentially access the
wrapped object. Consistency is based on expectations.

Operator-dot represents a fundamental shift in our expectations.

And that's probably the scariest part of it, and the prime reason why I
don't think it should exist.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6ca9b6c7-cd53-463e-b93f-7036111eef70%40isocpp.org.

------=_Part_1015_770977443.1476458595239
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, October 14, 2016 at 9:36:56 AM UTC-4, joseph...=
..@gmail.com 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">On Friday, 14 October 2016 00:52:53 UTC+8, Nicol Bolas  wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Thursday, October 13, 2=
016 at 4:27:51 AM UTC-4, <a>joseph....@gmail.com</a> wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div>On Thursday, 13 October 2016 02:31:06 UTC+8, N=
icol Bolas  wrote:=C2=A0<br></div></blockquote></div></blockquote><blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"></div></blockquote><div><br>No, you do not ha=
ve &quot;compile-time safety&quot;. What you <i>have</i> is language-level =
assurance that, if the user somehow managed to pass a null reference, then =
the user has <i>already</i> caused UB.<br><br>But the program as a whole ha=
s not been made any safer, either at compile time or runtime. It simply mak=
es the code more expressive of your intent (since null references are UB). =
But so too does `not_null&lt;T*&gt;`.<br><br>If a user did this:<br><br><di=
v style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);=
border-style:solid;border-width:1px"><code><div><span style=3D"color:#000">=
foo_not_null</span><span style=3D"color:#660">(</span><span style=3D"color:=
#000">get_a_pointer</span><span style=3D"color:#660">());</span></div></cod=
e></div><br>Where `foo_not_null` requires a non-NULL pointer, and `get_a_po=
inter` could return NULL. This is runtime-safe. However, doing the followin=
g doesn&#39;t become compile-time safe:<br><br><div style=3D"background-col=
or:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border=
-width:1px"><code><div><span style=3D"color:#000">foo_view</span><span styl=
e=3D"color:#660">(*</span><span style=3D"color:#000">get_a_pointer</span><s=
pan style=3D"color:#660">());</span><span style=3D"color:#000"><br></span><=
/div></code></div><br>Where `foo_view` takes a `view&lt;T&gt;`. No errors a=
re being caught here, at runtime or compile time. The user <i>must</i> chec=
k whether the pointer is NULL, and the user failed to do so.<br><br>This pr=
ogram has less safety than the `not_null` version.<br><br>At the very least=
, `view&lt;T&gt;` should have a constructor that takes a
 `T*` which throws if the pointer is NULL. Of course, if you did so, that w=
ould make `view&lt;T&gt;` equivalent to my suggested fixed version of `not_=
null&lt;T*&gt;`. So where is the advantage for `view&lt;T&gt;`?<br></div></=
div></blockquote><div><br>Okay, I understand your point. I guess my main pr=
oblem is with potential run-time cost where it isn&#39;t necessary.<br></di=
v></div></blockquote><div><br>Which, if my change for `not_null` goes throu=
gh, can be easily mitigated. The cost only happens when the pointer is intr=
oduced to `not_null`. If you pass a reference, there&#39;s no check.<br>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
>However, I have just realized that the GSL allows the behaviour of contrac=
t violations to be configured (it defaults to calling <span style=3D"font-f=
amily:courier new,monospace">std::terminate</span>). I assume this is becau=
se we currently lack the static analysis tools that the GSL is meant to ass=
ist. I am now assuming that the run-time check is intended to be removed in=
 release code (and if <span style=3D"font-family:courier new,monospace">not=
_null</span> were ever standardized), in favour of static detection of unch=
ecked pointer dereferencing and conversion to <span style=3D"font-family:co=
urier new,monospace">not_null</span>. This is supported by the description =
in <a href=3D"https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCo=
reGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-va=
lue" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;htt=
ps://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fisocpp%2FCppCoreGui=
delines%2Fblob%2Fmaster%2FCppCoreGuidelines.md%23f23-use-a-not_nullt-to-ind=
icate-that-null-is-not-a-valid-value\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQj=
CNG9axsOvk3ErZ8R5keZMgT7MYTQeA&#39;;return true;" onclick=3D"this.href=3D&#=
39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fisocpp%2FCppC=
oreGuidelines%2Fblob%2Fmaster%2FCppCoreGuidelines.md%23f23-use-a-not_nullt-=
to-indicate-that-null-is-not-a-valid-value\x26sa\x3dD\x26sntz\x3d1\x26usg\x=
3dAFQjCNG9axsOvk3ErZ8R5keZMgT7MYTQeA&#39;;return true;">F.23</a> of the C++=
 Core Guidelines.<br><br>If this were the case, <span style=3D"font-family:=
courier new,monospace">not_null</span> would not in fact be guaranteed to b=
e &quot;not null&quot; at run-time; the static analyzer would produce a war=
ning of unchecked conversion to <span style=3D"font-family:courier new,mono=
space">not_null</span> (though this check isn&#39;t specified in the C++ Co=
re Guidelines for some reason) and UB would arise potentially far from the =
warning site, wherever the <span style=3D"font-family:courier new,monospace=
">not_null</span> wrapper were eventually dereferenced. On the other hand, =
<span style=3D"font-family:courier new,monospace">view</span> <i>would</i> =
be guaranteed be &quot;not null&quot; at run-time; the static analyzer woul=
d produce a warning of an unchecked dereference of a raw pointer <i>at</i> =
the point at which UB arises. Another minor advantage is that you don&#39;t=
 need that extra check that I mentioned.<br><br>F.23 mentions that run-time=
 checks can be performed in debug builds, but most debuggers will catch a n=
ull pointer dereference, so I&#39;m not sure how useful this is.<br></div><=
/div></blockquote><div><br>It&#39;s very useful. A debugger can detect a NU=
LL pointer dereference, but only at the cite of use, not the place where th=
e NULL pointer <i>came from</i>. If the code that stored the pointer had us=
ed `not_null`, then they could get an error at the source of the pointer. O=
r at least, at the edges of the system that expected it to not be NULL, rat=
her than wherever it first got used.<br><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr">The problem with references is that they cannot be r=
eassigned, which makes them unusable in a lot of generic code (e.g. STL con=
tainers). As pointed out, <span style=3D"font-family:courier new,monospace"=
>std::reference_wrapper</span> exists for this purpose, but its API isn&#39=
;t particularly nice to use as a general-purpose reference wrapper. In my p=
roposal, I intend <span style=3D"font-family:courier new,monospace">view&lt=
;T&gt;</span> and <span style=3D"font-family:courier new,monospace">optiona=
l_view</span>&lt;T&gt; to work in tandem as replacements for <span style=3D=
"font-family:courier new,monospace">T&amp;</span> and <span style=3D"font-f=
amily:courier new,monospace">T*</span> respectively wherever they represent=
 &quot;references&quot; (in the general sense). I tried to make the case fo=
r <span style=3D"font-family:courier new,monospace">view&lt;T&gt;</span> ha=
ving some semantic advantage over <span style=3D"font-family:courier new,mo=
nospace">T&amp;</span>, but you&#39;ve made me reconsider my argument, sinc=
e <span style=3D"font-family:courier new,monospace">T&amp;</span> almost al=
ways means &quot;reference&quot; (in the general sense) and <span style=3D"=
font-family:courier new,monospace">T const&amp;</span> is almost always jus=
t to avoid an expensive copy. On the other hand, <span style=3D"font-family=
:courier new,monospace">optional_view&lt;T&gt;</span> does convey additiona=
l meaning that <span style=3D"font-family:courier new,monospace">T*</span> =
does not, since the meaning of <span style=3D"font-family:courier new,monos=
pace">T*</span> is so horribly overloaded in C++.</div></blockquote><div><b=
r>In general, yes. But &quot;in general&quot; is talking about the reams of=
 legacy code that exists out there. That legacy code isn&#39;t going to swi=
tch from `T*` to `optional_view&lt;T&gt;` no matter what.<br></div></div></=
blockquote><div><br>I&#39;m not entirely sure what you are responding to he=
re, but I didn&#39;t intend <span style=3D"font-family:courier new,monospac=
e">view</span> or <span style=3D"font-family:courier new,monospace">optiona=
l_view</span> to be for legacy code in particular (unlike not_null, which d=
oes appear to be geared towards improving the safety of legacy code). They =
are intended to compliment existing standard library types with a higher-le=
vel abstraction of the non-owning &quot;reference&quot; concept.<br></div><=
/div></blockquote><div><br>What I&#39;m getting at is that, in code written=
 for modern C++, it is reasonable to assume that `T*` has a specific meanin=
g: nullable, non-owning reference to a single object. So if you&#39;re writ=
ing modern C++, you don&#39;t need `optional_view&lt;T&gt;` to say what the=
 much shorter `T*` already says.<br><br>So `optional_view&lt;T&gt;` is only=
 advantageous when working with a codebase where `T*` does not consistently=
 have a specific meaning. Hopefully, we&#39;re not writing more of that kin=
d of code...<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
 dir=3D"ltr"><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"><div>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>but the=
 quest for the perfect &quot;smart reference&quot; design seems just out of=
 reach.</div></div></blockquote><div><br>It is &quot;out of reach&quot; onl=
y because your definition of &quot;perfect&quot; is inherently contradictor=
y. You define &quot;perfection&quot; as emulating C++ language references e=
xactly, while simultaneously allowing by-reference copying via operator=3D,=
 which C++ language references do not do.<br><br>Emulating language referen=
ces is a binary proposition. Either that&#39;s something you want, or its s=
omething you don&#39;t.<br></div></div></blockquote><div><br>I&#39;m confla=
ting C++ references and references in a general sense again. It is possible=
 to perfectly emulate C++ references (that would be my option 2). What I wa=
nt (consistent behaviour for copying both wrapper and wrapped objects) is o=
ut of reach when using operator dot overloading, so I don&#39;t use it.<spa=
n style=3D"font-family:courier new,monospace"></span><br>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div>It seems this is because t=
he design of reference types is fundamentally different from the design of =
value types in C++. Thus, <span style=3D"font-family:courier new,monospace"=
>view</span> and <span style=3D"font-family:courier new,monospace">optional=
_view</span> do not use operator dot overloading, because this seems to be =
the only way to get consistent behaviour when modifying both the wrapper an=
d when modifying the wrapped object.</div></div></blockquote><div><br>And y=
et, that&#39;s not true at all. Your option 1 above seems perfectly consist=
ent. Just like `a-&gt;foo =3D=3D b-&gt;foo`. It only looks odd because you =
expect `.` to mean &quot;access the wrapper&quot; instead of &quot;possibly=
 access the wrapped object&quot;.</div></div></blockquote><div><br>When I s=
ay it isn&#39;t consistent, I mean that if <span style=3D"font-family:couri=
er new,monospace">a.foo =3D b.foo</span> modifies the wrapped object, then =
I expect <span style=3D"font-family:courier new,monospace">a =3D b</span> t=
o modify the wrapped object as well. The problem is that there is only one =
<span style=3D"font-family:courier new,monospace">operator=3D</span>, and t=
wo functions I want it to perform. This is why I must, unfortunately, rely =
on <span style=3D"font-family:courier new,monospace">operator*</span> and <=
span style=3D"font-family:courier new,monospace">operator-&gt;</span> when =
referring to the wrapped object.</div></div></blockquote><div><br>So... why=
 is it consistent for `a-&gt;foo =3D b-&gt;foo` to have different behavior =
from `a =3D b`, yet `a.foo =3D b.foo` should have the same behavior?<br><br=
>The answer is simple: because you expect `-&gt;` to mean &quot;access wrap=
ped object&quot;, while you expect `.` to mean &quot;access handle&quot;. Y=
ou live in a world sans-operator-dot, so you don&#39;t expect `a.foo` to po=
tentially access the wrapped object. Consistency is based on expectations.<=
br><br>Operator-dot represents a fundamental shift in our expectations.<br>=
<br>And that&#39;s probably the scariest part of it, and the prime reason w=
hy I don&#39;t think it should exist.<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/6ca9b6c7-cd53-463e-b93f-7036111eef70%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6ca9b6c7-cd53-463e-b93f-7036111eef70=
%40isocpp.org</a>.<br />

------=_Part_1015_770977443.1476458595239--

------=_Part_1014_824200238.1476458595239--

.


Author: joseph.thomson@gmail.com
Date: Fri, 14 Oct 2016 09:14:30 -0700 (PDT)
Raw View
------=_Part_1375_1572935423.1476461670792
Content-Type: multipart/alternative;
 boundary="----=_Part_1376_1288719365.1476461670793"

------=_Part_1376_1288719365.1476461670793
Content-Type: text/plain; charset=UTF-8

On Friday, 14 October 2016 23:23:15 UTC+8, Nicol Bolas wrote:
>
> On Friday, October 14, 2016 at 9:36:56 AM UTC-4, joseph....@gmail.com
> wrote:
>>
>> On Friday, 14 October 2016 00:52:53 UTC+8, Nicol Bolas wrote:
>>>
>>> On Thursday, October 13, 2016 at 4:27:51 AM UTC-4, joseph....@gmail.com
>>> wrote:
>>>>
>>>> On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas wrote:
>>>>
>>>
>>> No, you do not have "compile-time safety". What you *have* is
>>> language-level assurance that, if the user somehow managed to pass a null
>>> reference, then the user has *already* caused UB.
>>>
>>> But the program as a whole has not been made any safer, either at
>>> compile time or runtime. It simply makes the code more expressive of your
>>> intent (since null references are UB). But so too does `not_null<T*>`.
>>>
>>> If a user did this:
>>>
>>> foo_not_null(get_a_pointer());
>>>
>>> Where `foo_not_null` requires a non-NULL pointer, and `get_a_pointer`
>>> could return NULL. This is runtime-safe. However, doing the following
>>> doesn't become compile-time safe:
>>>
>>> foo_view(*get_a_pointer());
>>>
>>> Where `foo_view` takes a `view<T>`. No errors are being caught here, at
>>> runtime or compile time. The user *must* check whether the pointer is
>>> NULL, and the user failed to do so.
>>>
>>> This program has less safety than the `not_null` version.
>>>
>>> At the very least, `view<T>` should have a constructor that takes a `T*`
>>> which throws if the pointer is NULL. Of course, if you did so, that would
>>> make `view<T>` equivalent to my suggested fixed version of `not_null<T*>`.
>>> So where is the advantage for `view<T>`?
>>>
>>
>> Okay, I understand your point. I guess my main problem is with potential
>> run-time cost where it isn't necessary.
>>
>
> Which, if my change for `not_null` goes through, can be easily mitigated.
> The cost only happens when the pointer is introduced to `not_null`. If you
> pass a reference, there's no check.
>

Yup. I'll be watching your issue report. I'm interested to find out more
about the intended design of not_null.


> However, I have just realized that the GSL allows the behaviour of
>> contract violations to be configured (it defaults to calling
>> std::terminate). I assume this is because we currently lack the static
>> analysis tools that the GSL is meant to assist. I am now assuming that the
>> run-time check is intended to be removed in release code (and if not_null
>> were ever standardized), in favour of static detection of unchecked pointer
>> dereferencing and conversion to not_null. This is supported by the
>> description in F.23
>> <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-value>
>> of the C++ Core Guidelines.
>>
>> If this were the case, not_null would not in fact be guaranteed to be
>> "not null" at run-time; the static analyzer would produce a warning of
>> unchecked conversion to not_null (though this check isn't specified in
>> the C++ Core Guidelines for some reason) and UB would arise potentially far
>> from the warning site, wherever the not_null wrapper were eventually
>> dereferenced. On the other hand, view *would* be guaranteed be "not
>> null" at run-time; the static analyzer would produce a warning of an
>> unchecked dereference of a raw pointer *at* the point at which UB
>> arises. Another minor advantage is that you don't need that extra check
>> that I mentioned.
>>
>> F.23 mentions that run-time checks can be performed in debug builds, but
>> most debuggers will catch a null pointer dereference, so I'm not sure how
>> useful this is.
>>
>
> It's very useful. A debugger can detect a NULL pointer dereference, but
> only at the cite of use, not the place where the NULL pointer *came from*.
> If the code that stored the pointer had used `not_null`, then they could
> get an error at the source of the pointer. Or at least, at the edges of the
> system that expected it to not be NULL, rather than wherever it first got
> used.
>

Sorry, you are right. It is important to the design of not_null. I was
getting not_null<T*> and T& mixed up in my mind. Null pointer dereference
will only happen at the source when using T& instead of not_null<T*>.


> The problem with references is that they cannot be reassigned, which makes
>>>> them unusable in a lot of generic code (e.g. STL containers). As pointed
>>>> out, std::reference_wrapper exists for this purpose, but its API isn't
>>>> particularly nice to use as a general-purpose reference wrapper. In my
>>>> proposal, I intend view<T> and optional_view<T> to work in tandem as
>>>> replacements for T& and T* respectively wherever they represent
>>>> "references" (in the general sense). I tried to make the case for
>>>> view<T> having some semantic advantage over T&, but you've made me
>>>> reconsider my argument, since T& almost always means "reference" (in
>>>> the general sense) and T const& is almost always just to avoid an
>>>> expensive copy. On the other hand, optional_view<T> does convey
>>>> additional meaning that T* does not, since the meaning of T* is so
>>>> horribly overloaded in C++.
>>>>
>>>
>>> In general, yes. But "in general" is talking about the reams of legacy
>>> code that exists out there. That legacy code isn't going to switch from
>>> `T*` to `optional_view<T>` no matter what.
>>>
>>
>> I'm not entirely sure what you are responding to here, but I didn't
>> intend view or optional_view to be for legacy code in particular (unlike
>> not_null, which does appear to be geared towards improving the safety of
>> legacy code). They are intended to compliment existing standard library
>> types with a higher-level abstraction of the non-owning "reference" concept.
>>
>
> What I'm getting at is that, in code written for modern C++, it is
> reasonable to assume that `T*` has a specific meaning: nullable, non-owning
> reference to a single object. So if you're writing modern C++, you don't
> need `optional_view<T>` to say what the much shorter `T*` already says.
>
> So `optional_view<T>` is only advantageous when working with a codebase
> where `T*` does not consistently have a specific meaning. Hopefully, we're
> not writing more of that kind of code...
>

This is a fair argument, and a reasonable conclusion if you don't find any
of the other features of view and optional_view compelling.


> but the quest for the perfect "smart reference" design seems just out of
>>>> reach.
>>>>
>>>
>>> It is "out of reach" only because your definition of "perfect" is
>>> inherently contradictory. You define "perfection" as emulating C++ language
>>> references exactly, while simultaneously allowing by-reference copying via
>>> operator=, which C++ language references do not do.
>>>
>>> Emulating language references is a binary proposition. Either that's
>>> something you want, or its something you don't.
>>>
>>
>> I'm conflating C++ references and references in a general sense again. It
>> is possible to perfectly emulate C++ references (that would be my option
>> 2). What I want (consistent behaviour for copying both wrapper and wrapped
>> objects) is out of reach when using operator dot overloading, so I don't
>> use it.
>>
>>
>>> It seems this is because the design of reference types is fundamentally
>>>> different from the design of value types in C++. Thus, view and
>>>> optional_view do not use operator dot overloading, because this seems
>>>> to be the only way to get consistent behaviour when modifying both the
>>>> wrapper and when modifying the wrapped object.
>>>>
>>>
>>> And yet, that's not true at all. Your option 1 above seems perfectly
>>> consistent. Just like `a->foo == b->foo`. It only looks odd because you
>>> expect `.` to mean "access the wrapper" instead of "possibly access the
>>> wrapped object".
>>>
>>
>> When I say it isn't consistent, I mean that if a.foo = b.foo modifies
>> the wrapped object, then I expect a = b to modify the wrapped object as
>> well. The problem is that there is only one operator=, and two functions
>> I want it to perform. This is why I must, unfortunately, rely on
>> operator* and operator-> when referring to the wrapped object.
>>
>
> So... why is it consistent for `a->foo = b->foo` to have different
> behavior from `a = b`, yet `a.foo = b.foo` should have the same behavior?
>

Maybe it will be clearer if I write a->foo = b->foo in a different way.
This is the "consistent" behaviour I want:

(*a) = (*b); // modifies wrapped object
(*a).foo = (*b).foo; // modifies wrapped object

a.foo = b.foo; // modifies wrapper
a = b; // modifies wrapper

The answer is simple: because you expect `->` to mean "access wrapped
> object", while you expect `.` to mean "access handle". You live in a world
> sans-operator-dot, so you don't expect `a.foo` to potentially access the
> wrapped object. Consistency is based on expectations.
>

So you understand what I'm saying. You just wouldn't call it "consistency".
Perhaps "symmetry" is a better term. Operator dot overloading breaks the
symmetry of C++ object syntax. Of course, C++ references already have this
asymmetry, but I wonder if this too was a mistake: perhaps references
should have been designed to be de*referenced* like pointers. Of course,
this opens up a whole new incredibly complex can of worms, but it's an
interesting thought. Perhaps this is the idea I am trying to model with view
and optional_view.


> Operator-dot represents a fundamental shift in our expectations.
>
> And that's probably the scariest part of it, and the prime reason why I
> don't think it should exist.
>

You don't? I assumed you were all for it. Well, then we agree on something
:)

--
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/5c4295d5-c02b-4747-bc7b-b5eb707e5fba%40isocpp.org.

------=_Part_1376_1288719365.1476461670793
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, 14 October 2016 23:23:15 UTC+8, Nicol Bolas  wr=
ote:<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">On Friday=
, October 14, 2016 at 9:36:56 AM UTC-4, <a>joseph....@gmail.com</a> 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">On Friday, 14 Octob=
er 2016 00:52:53 UTC+8, Nicol Bolas  wrote:<blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr">On Thursday, October 13, 2016 at 4:27:51 AM UTC-4,=
 <a>joseph....@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div>On Thursday, 13 October 2016 02:31:06 UTC+8, Nicol Bolas  wrote:=C2=
=A0<br></div></blockquote></div></blockquote><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"></div></blockquote><div><br>No, you do not have &quot;compile-time=
 safety&quot;. What you <i>have</i> is language-level assurance that, if th=
e user somehow managed to pass a null reference, then the user has <i>alrea=
dy</i> caused UB.<br><br>But the program as a whole has not been made any s=
afer, either at compile time or runtime. It simply makes the code more expr=
essive of your intent (since null references are UB). But so too does `not_=
null&lt;T*&gt;`.<br><br>If a user did this:<br><br><div style=3D"background=
-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bo=
rder-width:1px"><code><div><span style=3D"color:#000">foo_not_null</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">get_a_pointer</=
span><span style=3D"color:#660">());</span></div></code></div><br>Where `fo=
o_not_null` requires a non-NULL pointer, and `get_a_pointer` could return N=
ULL. This is runtime-safe. However, doing the following doesn&#39;t become =
compile-time safe:<br><br><div style=3D"background-color:rgb(250,250,250);b=
order-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><di=
v><span style=3D"color:#000">foo_view</span><span style=3D"color:#660">(*</=
span><span style=3D"color:#000">get_a_pointer</span><span style=3D"color:#6=
60">());</span><span style=3D"color:#000"><br></span></div></code></div><br=
>Where `foo_view` takes a `view&lt;T&gt;`. No errors are being caught here,=
 at runtime or compile time. The user <i>must</i> check whether the pointer=
 is NULL, and the user failed to do so.<br><br>This program has less safety=
 than the `not_null` version.<br><br>At the very least, `view&lt;T&gt;` sho=
uld have a constructor that takes a
 `T*` which throws if the pointer is NULL. Of course, if you did so, that w=
ould make `view&lt;T&gt;` equivalent to my suggested fixed version of `not_=
null&lt;T*&gt;`. So where is the advantage for `view&lt;T&gt;`?<br></div></=
div></blockquote><div><br>Okay, I understand your point. I guess my main pr=
oblem is with potential run-time cost where it isn&#39;t necessary.<br></di=
v></div></blockquote><div><br>Which, if my change for `not_null` goes throu=
gh, can be easily mitigated. The cost only happens when the pointer is intr=
oduced to `not_null`. If you pass a reference, there&#39;s no check.<br></d=
iv></div></blockquote><div>=C2=A0<br>Yup. I&#39;ll be watching your issue r=
eport. I&#39;m interested to find out more about the intended design of <sp=
an style=3D"font-family: courier new,monospace;">not_null</span>.<br>=C2=A0=
<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><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"><div>However, I have =
just realized that the GSL allows the behaviour of contract violations to b=
e configured (it defaults to calling <span style=3D"font-family:courier new=
,monospace">std::terminate</span>). I assume this is because we currently l=
ack the static analysis tools that the GSL is meant to assist. I am now ass=
uming that the run-time check is intended to be removed in release code (an=
d if <span style=3D"font-family:courier new,monospace">not_null</span> were=
 ever standardized), in favour of static detection of unchecked pointer der=
eferencing and conversion to <span style=3D"font-family:courier new,monospa=
ce">not_null</span>. This is supported by the description in <a href=3D"htt=
ps://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f=
23-use-a-not_nullt-to-indicate-that-null-is-not-a-valid-value" rel=3D"nofol=
low" target=3D"_blank" onmousedown=3D"this.href=3D&#39;https://www.google.c=
om/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fisocpp%2FCppCoreGuidelines%2Fblob%2F=
master%2FCppCoreGuidelines.md%23f23-use-a-not_nullt-to-indicate-that-null-i=
s-not-a-valid-value\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG9axsOvk3ErZ8R5=
keZMgT7MYTQeA&#39;;return true;" onclick=3D"this.href=3D&#39;https://www.go=
ogle.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fisocpp%2FCppCoreGuidelines%2Fb=
lob%2Fmaster%2FCppCoreGuidelines.md%23f23-use-a-not_nullt-to-indicate-that-=
null-is-not-a-valid-value\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG9axsOvk3=
ErZ8R5keZMgT7MYTQeA&#39;;return true;">F.23</a> of the C++ Core Guidelines.=
<br><br>If this were the case, <span style=3D"font-family:courier new,monos=
pace">not_null</span> would not in fact be guaranteed to be &quot;not null&=
quot; at run-time; the static analyzer would produce a warning of unchecked=
 conversion to <span style=3D"font-family:courier new,monospace">not_null</=
span> (though this check isn&#39;t specified in the C++ Core Guidelines for=
 some reason) and UB would arise potentially far from the warning site, whe=
rever the <span style=3D"font-family:courier new,monospace">not_null</span>=
 wrapper were eventually dereferenced. On the other hand, <span style=3D"fo=
nt-family:courier new,monospace">view</span> <i>would</i> be guaranteed be =
&quot;not null&quot; at run-time; the static analyzer would produce a warni=
ng of an unchecked dereference of a raw pointer <i>at</i> the point at whic=
h UB arises. Another minor advantage is that you don&#39;t need that extra =
check that I mentioned.<br><br>F.23 mentions that run-time checks can be pe=
rformed in debug builds, but most debuggers will catch a null pointer deref=
erence, so I&#39;m not sure how useful this is.<br></div></div></blockquote=
><div><br>It&#39;s very useful. A debugger can detect a NULL pointer derefe=
rence, but only at the cite of use, not the place where the NULL pointer <i=
>came from</i>. If the code that stored the pointer had used `not_null`, th=
en they could get an error at the source of the pointer. Or at least, at th=
e edges of the system that expected it to not be NULL, rather than wherever=
 it first got used.<br></div></div></blockquote><div><br>Sorry, you are rig=
ht. It is important to the design of <span style=3D"font-family: courier ne=
w,monospace;">not_null</span>. I was getting <span style=3D"font-family: co=
urier new,monospace;">not_null&lt;T*&gt;</span> and <span style=3D"font-fam=
ily: courier new,monospace;">T&amp;</span> mixed up in my mind. Null pointe=
r dereference will only happen at the source when using <span style=3D"font=
-family: courier new,monospace;">T&amp;</span> instead of <span style=3D"fo=
nt-family: courier new,monospace;">not_null&lt;T*&gt;</span>.<br>=C2=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><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"><div></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr">The problem with references is t=
hat they cannot be reassigned, which makes them unusable in a lot of generi=
c code (e.g. STL containers). As pointed out, <span style=3D"font-family:co=
urier new,monospace">std::reference_wrapper</span> exists for this purpose,=
 but its API isn&#39;t particularly nice to use as a general-purpose refere=
nce wrapper. In my proposal, I intend <span style=3D"font-family:courier ne=
w,monospace">view&lt;T&gt;</span> and <span style=3D"font-family:courier ne=
w,monospace">optional_view</span>&lt;T&gt; to work in tandem as replacement=
s for <span style=3D"font-family:courier new,monospace">T&amp;</span> and <=
span style=3D"font-family:courier new,monospace">T*</span> respectively whe=
rever they represent &quot;references&quot; (in the general sense). I tried=
 to make the case for <span style=3D"font-family:courier new,monospace">vie=
w&lt;T&gt;</span> having some semantic advantage over <span style=3D"font-f=
amily:courier new,monospace">T&amp;</span>, but you&#39;ve made me reconsid=
er my argument, since <span style=3D"font-family:courier new,monospace">T&a=
mp;</span> almost always means &quot;reference&quot; (in the general sense)=
 and <span style=3D"font-family:courier new,monospace">T const&amp;</span> =
is almost always just to avoid an expensive copy. On the other hand, <span =
style=3D"font-family:courier new,monospace">optional_view&lt;T&gt;</span> d=
oes convey additional meaning that <span style=3D"font-family:courier new,m=
onospace">T*</span> does not, since the meaning of <span style=3D"font-fami=
ly:courier new,monospace">T*</span> is so horribly overloaded in C++.</div>=
</blockquote><div><br>In general, yes. But &quot;in general&quot; is talkin=
g about the reams of legacy code that exists out there. That legacy code is=
n&#39;t going to switch from `T*` to `optional_view&lt;T&gt;` no matter wha=
t.<br></div></div></blockquote><div><br>I&#39;m not entirely sure what you =
are responding to here, but I didn&#39;t intend <span style=3D"font-family:=
courier new,monospace">view</span> or <span style=3D"font-family:courier ne=
w,monospace">optional_view</span> to be for legacy code in particular (unli=
ke not_null, which does appear to be geared towards improving the safety of=
 legacy code). They are intended to compliment existing standard library ty=
pes with a higher-level abstraction of the non-owning &quot;reference&quot;=
 concept.<br></div></div></blockquote><div><br>What I&#39;m getting at is t=
hat, in code written for modern C++, it is reasonable to assume that `T*` h=
as a specific meaning: nullable, non-owning reference to a single object. S=
o if you&#39;re writing modern C++, you don&#39;t need `optional_view&lt;T&=
gt;` to say what the much shorter `T*` already says.<br><br>So `optional_vi=
ew&lt;T&gt;` is only advantageous when working with a codebase where `T*` d=
oes not consistently have a specific meaning. Hopefully, we&#39;re not writ=
ing more of that kind of code...<br></div></div></blockquote><div><br>This =
is a fair argument, and a reasonable conclusion if you don&#39;t find any o=
f the other features of <span style=3D"font-family: courier new,monospace;"=
>view</span> and <span style=3D"font-family: courier new,monospace;">option=
al_view</span> compelling.<br>=C2=A0</div><blockquote class=3D"gmail_quote"=
 style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-=
left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;m=
argin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div></div><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"><di=
v>but the quest for the perfect &quot;smart reference&quot; design seems ju=
st out of reach.</div></div></blockquote><div><br>It is &quot;out of reach&=
quot; only because your definition of &quot;perfect&quot; is inherently con=
tradictory. You define &quot;perfection&quot; as emulating C++ language ref=
erences exactly, while simultaneously allowing by-reference copying via ope=
rator=3D, which C++ language references do not do.<br><br>Emulating languag=
e references is a binary proposition. Either that&#39;s something you want,=
 or its something you don&#39;t.<br></div></div></blockquote><div><br>I&#39=
;m conflating C++ references and references in a general sense again. It is=
 possible to perfectly emulate C++ references (that would be my option 2). =
What I want (consistent behaviour for copying both wrapper and wrapped obje=
cts) is out of reach when using operator dot overloading, so I don&#39;t us=
e it.<span style=3D"font-family:courier new,monospace"></span><br>=C2=A0</d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>It seems this is =
because the design of reference types is fundamentally different from the d=
esign of value types in C++. Thus, <span style=3D"font-family:courier new,m=
onospace">view</span> and <span style=3D"font-family:courier new,monospace"=
>optional_view</span> do not use operator dot overloading, because this see=
ms to be the only way to get consistent behaviour when modifying both the w=
rapper and when modifying the wrapped object.</div></div></blockquote><div>=
<br>And yet, that&#39;s not true at all. Your option 1 above seems perfectl=
y consistent. Just like `a-&gt;foo =3D=3D b-&gt;foo`. It only looks odd bec=
ause you expect `.` to mean &quot;access the wrapper&quot; instead of &quot=
;possibly access the wrapped object&quot;.</div></div></blockquote><div><br=
>When I say it isn&#39;t consistent, I mean that if <span style=3D"font-fam=
ily:courier new,monospace">a.foo =3D b.foo</span> modifies the wrapped obje=
ct, then I expect <span style=3D"font-family:courier new,monospace">a =3D b=
</span> to modify the wrapped object as well. The problem is that there is =
only one <span style=3D"font-family:courier new,monospace">operator=3D</spa=
n>, and two functions I want it to perform. This is why I must, unfortunate=
ly, rely on <span style=3D"font-family:courier new,monospace">operator*</sp=
an> and <span style=3D"font-family:courier new,monospace">operator-&gt;</sp=
an> when referring to the wrapped object.</div></div></blockquote><div><br>=
So... why is it consistent for `a-&gt;foo =3D b-&gt;foo` to have different =
behavior from `a =3D b`, yet `a.foo =3D b.foo` should have the same behavio=
r?<br></div></div></blockquote><div><br>Maybe it will be clearer if I write=
 a-&gt;foo =3D b-&gt;foo in a different way. This is the &quot;consistent&q=
uot; behaviour I want:<br><br><span style=3D"font-family: courier new,monos=
pace;">(*a) =3D (*b); // modifies wrapped object<br>(*a).foo =3D (*b).foo; =
// modifies wrapped object<br><br>a.foo =3D b.foo; // modifies wrapper<br>a=
 =3D b; // modifies wrapper</span><br><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div>The answer is simple: because you e=
xpect `-&gt;` to mean &quot;access wrapped object&quot;, while you expect `=
..` to mean &quot;access handle&quot;. You live in a world sans-operator-dot=
, so you don&#39;t expect `a.foo` to potentially access the wrapped object.=
 Consistency is based on expectations.<br></div></div></blockquote><div><br=
>So you understand what I&#39;m saying. You just wouldn&#39;t call it &quot=
;consistency&quot;. Perhaps &quot;symmetry&quot; is a better term. Operator=
 dot overloading breaks the symmetry of C++ object syntax. Of course, C++ r=
eferences already have this asymmetry, but I wonder if this too was a mista=
ke: perhaps references should have been designed to be de<b>referenced</b> =
like pointers. Of course, this opens up a whole new incredibly complex can =
of worms, but it&#39;s an interesting thought. Perhaps this is the idea I a=
m trying to model with <span style=3D"font-family: courier new,monospace;">=
view</span> and <span style=3D"font-family: courier new,monospace;">optiona=
l_view</span>.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div dir=3D"ltr"><div>Operator-dot represents a fundamental shift in our ex=
pectations.<br><br></div></div></blockquote><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div>And that&#39;s probably the scariest pa=
rt of it, and the prime reason why I don&#39;t think it should exist.<br></=
div></div></blockquote><div><br>You don&#39;t? I assumed you were all for i=
t. Well, then we agree on something :)<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/5c4295d5-c02b-4747-bc7b-b5eb707e5fba%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5c4295d5-c02b-4747-bc7b-b5eb707e5fba=
%40isocpp.org</a>.<br />

------=_Part_1376_1288719365.1476461670793--

------=_Part_1375_1572935423.1476461670792--

.


Author: mihailnajdenov@gmail.com
Date: Sat, 15 Oct 2016 02:37:26 -0700 (PDT)
Raw View
------=_Part_1131_91260435.1476524246853
Content-Type: multipart/alternative;
 boundary="----=_Part_1132_493348845.1476524246854"

------=_Part_1132_493348845.1476524246854
Content-Type: text/plain; charset=UTF-8


>
> ...
>
>> Operator-dot represents a fundamental shift in our expectations.
>>
>> And that's probably the scariest part of it, and the prime reason why I
>> don't think it should exist.
>>
>
> You don't? I assumed you were all for it. Well, then we agree on something
> :)
>

 I am not sure, you all aware of the one of the other proposals. Namely
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0352r0.pdf
<http://www.google.com/url?q=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0352r0.pdf&sa=D&sntz=1&usg=AFQjCNHYZPJtfbho-i-q7MgRJPt5k81BRw>
It does not override operator.(). It "just" reuses operator T() to "convert
to" the required object.

The trick is, it advertises possible convert-on-dot classes, reusing the
"subclass" semantics and syntax.
This way using the dot to access a different object no longer feels like
magic, because all the possible interfaces of the class are stated
as "subclasses" in the class definition, like they always had!

I personally like this proposal very much because it uses old mechanics to
create new scenarios.
It feels like a natural extension to both.

Consider:

 struct A
 {
     int i = 1;
 };

 struct B
 {
     operator A&() { return a; }
     A a;
 };

int main() {

    B b;
    auto i = static_cast<A&>(b).i;

    std::cout << i;
}

This is possible and valid today.

As well as:


 struct A
 {
     int i = 1;
 };

 struct B : public A
 {

 };

int main() {

    B b;
    auto i = b.i;

    std::cout << i;
}


And with the proposal:

 struct A
 {
     int i = 1;
 };

 struct B : public using A
 {
     operator A&() { return a; }
     A a;
 };

int main() {

    B b;
    auto i = b.i;

    std::cout << i;
}

*Does not look that bad at all -* You mix both to get the benefits of both!

--
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/5a441473-cd1d-48e8-8069-c95f78b9bb68%40isocpp.org.

------=_Part_1132_493348845.1476524246854
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>...</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div>Operator-dot represents a fundamental shift in our expectations.<br><b=
r></div></div></blockquote><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"><div>And that&#39;s probably the scariest part of it, and the prim=
e reason why I don&#39;t think it should exist.<br></div></div></blockquote=
><div><br>You don&#39;t? I assumed you were all for it. Well, then we agree=
 on something :)<br></div></div></blockquote><div><br></div><div>=C2=A0I am=
 not sure, you all aware of the one of the other proposals. Namely <a onmou=
sedown=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.=
open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0352r0.pdf\x26s=
a\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHYZPJtfbho-i-q7MgRJPt5k81BRw&#39;;retur=
n true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A=
%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0352r=
0.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHYZPJtfbho-i-q7MgRJPt5k81BRw&=
#39;;return true;" href=3D"http://www.google.com/url?q=3Dhttp%3A%2F%2Fwww.o=
pen-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0352r0.pdf&amp;s=
a=3DD&amp;sntz=3D1&amp;usg=3DAFQjCNHYZPJtfbho-i-q7MgRJPt5k81BRw" target=3D"=
_blank" rel=3D"nofollow">http://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/p=
apers/2016/<wbr>p0352r0.pdf</a></div><div>It does not override operator.().=
 It &quot;just&quot; reuses operator T() to &quot;convert to&quot; the requ=
ired object. </div><div><br></div><div>The trick is, it advertises possible=
 convert-on-dot classes, reusing=C2=A0the &quot;subclass&quot; semantics an=
d syntax.</div><div>This way using the dot to access a=C2=A0different objec=
t no longer feels like magic, because=C2=A0all the possible interfaces=C2=
=A0of the class are stated as=C2=A0&quot;subclasses&quot; in the class defi=
nition, like they always had!</div><div><br></div><div>I personally like th=
is proposal very much because it uses old mechanics to create new scenarios=
.. </div><div>It feels like a natural extension to both. </div><div><br></di=
v><div>Consider:</div><div><br></div><div><div class=3D"prettyprint" style=
=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background=
-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subp=
rettyprint"><span class=3D"styled-by-prettify" style=3D"color: #008;"><font=
 color=3D"rgb(0,0,0)">=C2=A0struct A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=A0=
 int i =3D 1;<br>=C2=A0};</font></span></div><div><br></div><div class=3D"s=
ubprettyprint"><span class=3D"styled-by-prettify" style=3D"color: #008;"><f=
ont color=3D"rgb(0,0,0)">=C2=A0struct B<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=
=A0 operator A&amp;() { return a; }<br>=C2=A0=C2=A0=C2=A0=C2=A0 A a;<br>=C2=
=A0};<br>=C2=A0<br>int main() {<br>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=
=A0 B b;<br>=C2=A0=C2=A0=C2=A0 auto i =3D static_cast&lt;A&amp;&gt;(b).i;<b=
r>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; i;<br>}</fon=
t></span><span class=3D"styled-by-prettify" style=3D"color: #000;"><br></sp=
an></div></code></div><br></div><div>This is possible and valid today.</div=
><div><br></div><div>As well as:</div><div><br></div><div><div class=3D"pre=
ttyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-w=
ord; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><sp=
an class=3D"styled-by-prettify" style=3D"color: #606;"></span><div class=3D=
"subprettyprint"><span class=3D"styled-by-prettify" style=3D"color: #606;">=
<font color=3D"rgb(34,34,34)" face=3D"Arial" style=3D"background-color: tra=
nsparent;"><br>=C2=A0struct A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=A0 int i =
=3D 1;<br>=C2=A0};</font></span></div><div><br></div><div class=3D"subprett=
yprint"><span class=3D"styled-by-prettify" style=3D"color: #606;"><font col=
or=3D"rgb(34,34,34)" face=3D"Arial" style=3D"background-color: transparent;=
">=C2=A0struct B : public A<br>=C2=A0{</font></span></div><div><br></div><d=
iv class=3D"subprettyprint"><span class=3D"styled-by-prettify" style=3D"col=
or: #606;"><font color=3D"rgb(34,34,34)" face=3D"Arial" style=3D"background=
-color: transparent;">=C2=A0};<br>=C2=A0<br>int main() {<br>=C2=A0=C2=A0=C2=
=A0 <br>=C2=A0=C2=A0=C2=A0 B b;<br>=C2=A0=C2=A0=C2=A0 auto i =3D b.i;<br>=
=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; i;<br>}</font>=
</span><span class=3D"styled-by-prettify" style=3D"color: #660;"></span></d=
iv></code><br></div></div><div><br></div><div>And with=C2=A0the proposal:</=
div><div><br></div><div><div class=3D"prettyprint" style=3D"border: 1px sol=
id rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 25=
0, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span c=
lass=3D"styled-by-prettify" style=3D"color: #606;"><font color=3D"rgb(34,34=
,34)" face=3D"Arial" style=3D"background-color: transparent;">=C2=A0struct =
A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=A0 int i =3D 1;<br>=C2=A0};</font></s=
pan></div><div><br></div><div class=3D"subprettyprint"><span class=3D"style=
d-by-prettify" style=3D"color: #606;"><font color=3D"rgb(34,34,34)" face=3D=
"Arial" style=3D"background-color: transparent;">=C2=A0struct B : public us=
ing A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=A0 operator A&amp;() { return a; =
}<br>=C2=A0=C2=A0=C2=A0=C2=A0 A a;<br>=C2=A0};<br>=C2=A0<br>int main() {<br=
>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0 B b;<br>=C2=A0=C2=A0=C2=A0 auto =
i =3D b.i;<br>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; =
i;<br>}</font></span><span class=3D"styled-by-prettify" style=3D"color: #66=
0;"></span></div></code></div><br></div><div><i>Does not look that bad at a=
ll -</i>=C2=A0You mix both to get the benefits of both! </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/5a441473-cd1d-48e8-8069-c95f78b9bb68%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5a441473-cd1d-48e8-8069-c95f78b9bb68=
%40isocpp.org</a>.<br />

------=_Part_1132_493348845.1476524246854--

------=_Part_1131_91260435.1476524246853--

.


Author: joseph.thomson@gmail.com
Date: Wed, 19 Oct 2016 00:47:09 -0700 (PDT)
Raw View
------=_Part_223_375426593.1476863230143
Content-Type: multipart/alternative;
 boundary="----=_Part_224_248488012.1476863230144"

------=_Part_224_248488012.1476863230144
Content-Type: text/plain; charset=UTF-8

Thanks for the info. This actually seems like a very nice proposal. In
fact, it has made me think about how propagate_const could be implemented
more flexibly with such a feature.

On Saturday, 15 October 2016 17:37:27 UTC+8, mihailn...@gmail.com wrote:
>
> ...
>>
>>> Operator-dot represents a fundamental shift in our expectations.
>>>
>>> And that's probably the scariest part of it, and the prime reason why I
>>> don't think it should exist.
>>>
>>
>> You don't? I assumed you were all for it. Well, then we agree on
>> something :)
>>
>
>  I am not sure, you all aware of the one of the other proposals. Namely
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0352r0.pdf
> <http://www.google.com/url?q=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0352r0.pdf&sa=D&sntz=1&usg=AFQjCNHYZPJtfbho-i-q7MgRJPt5k81BRw>
> It does not override operator.(). It "just" reuses operator T() to
> "convert to" the required object.
>
> The trick is, it advertises possible convert-on-dot classes, reusing the
> "subclass" semantics and syntax.
> This way using the dot to access a different object no longer feels like
> magic, because all the possible interfaces of the class are stated
> as "subclasses" in the class definition, like they always had!
>
> I personally like this proposal very much because it uses old mechanics to
> create new scenarios.
> It feels like a natural extension to both.
>
> Consider:
>
>  struct A
>  {
>      int i = 1;
>  };
>
>  struct B
>  {
>      operator A&() { return a; }
>      A a;
>  };
>
> int main() {
>
>     B b;
>     auto i = static_cast<A&>(b).i;
>
>     std::cout << i;
> }
>
> This is possible and valid today.
>
> As well as:
>
>
>  struct A
>  {
>      int i = 1;
>  };
>
>  struct B : public A
>  {
>
>  };
>
> int main() {
>
>     B b;
>     auto i = b.i;
>
>     std::cout << i;
> }
>
>
> And with the proposal:
>
>  struct A
>  {
>      int i = 1;
>  };
>
>  struct B : public using A
>  {
>      operator A&() { return a; }
>      A a;
>  };
>
> int main() {
>
>     B b;
>     auto i = b.i;
>
>     std::cout << i;
> }
>
> *Does not look that bad at all -* You mix both to get the benefits of
> both!
>

--
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/74d6d50b-fe9e-4517-a18b-0316ffb96060%40isocpp.org.

------=_Part_224_248488012.1476863230144
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Thanks for the info. This actually seems like a very nice =
proposal. In fact, it has made me think about how propagate_const could be =
implemented more flexibly with such a feature.<br><br>On Saturday, 15 Octob=
er 2016 17:37:27 UTC+8, mihailn...@gmail.com  wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><div>...</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div>Operator-dot represents a fundamental shift in our e=
xpectations.<br><br></div></div></blockquote><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><div>And that&#39;s probably the scariest part o=
f it, and the prime reason why I don&#39;t think it should exist.<br></div>=
</div></blockquote><div><br>You don&#39;t? I assumed you were all for it. W=
ell, then we agree on something :)<br></div></div></blockquote><div><br></d=
iv><div>=C2=A0I am not sure, you all aware of the one of the other proposal=
s. Namely <a href=3D"http://www.google.com/url?q=3Dhttp%3A%2F%2Fwww.open-st=
d.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2016%2Fp0352r0.pdf&amp;sa=3DD&=
amp;sntz=3D1&amp;usg=3DAFQjCNHYZPJtfbho-i-q7MgRJPt5k81BRw" rel=3D"nofollow"=
 target=3D"_blank" onmousedown=3D"this.href=3D&#39;http://www.google.com/ur=
l?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2=
F2016%2Fp0352r0.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHYZPJtfbho-i-q7=
MgRJPt5k81BRw&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%=
2Fpapers%2F2016%2Fp0352r0.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHYZPJ=
tfbho-i-q7MgRJPt5k81BRw&#39;;return true;">http://www.open-std.org/jtc1/<wb=
r>sc22/wg21/docs/papers/2016/<wbr>p0352r0.pdf</a></div><div>It does not ove=
rride operator.(). It &quot;just&quot; reuses operator T() to &quot;convert=
 to&quot; the required object. </div><div><br></div><div>The trick is, it a=
dvertises possible convert-on-dot classes, reusing=C2=A0the &quot;subclass&=
quot; semantics and syntax.</div><div>This way using the dot to access a=C2=
=A0different object no longer feels like magic, because=C2=A0all the possib=
le interfaces=C2=A0of the class are stated as=C2=A0&quot;subclasses&quot; i=
n the class definition, like they always had!</div><div><br></div><div>I pe=
rsonally like this proposal very much because it uses old mechanics to crea=
te new scenarios. </div><div>It feels like a natural extension to both. </d=
iv><div><br></div><div>Consider:</div><div><br></div><div><div style=3D"bor=
der:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(25=
0,250,250)"><code><div><span style=3D"color:#008"><font color=3D"rgb(0,0,0)=
">=C2=A0struct A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=A0 int i =3D 1;<br>=C2=
=A0};</font></span></div><div><br></div><div><span style=3D"color:#008"><fo=
nt color=3D"rgb(0,0,0)">=C2=A0struct B<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=
=A0 operator A&amp;() { return a; }<br>=C2=A0=C2=A0=C2=A0=C2=A0 A a;<br>=C2=
=A0};<br>=C2=A0<br>int main() {<br>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=
=A0 B b;<br>=C2=A0=C2=A0=C2=A0 auto i =3D static_cast&lt;A&amp;&gt;(b).i;<b=
r>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; i;<br>}</fon=
t></span><span style=3D"color:#000"><br></span></div></code></div><br></div=
><div>This is possible and valid today.</div><div><br></div><div>As well as=
:</div><div><br></div><div><div style=3D"border:1px solid rgb(187,187,187);=
word-wrap:break-word;background-color:rgb(250,250,250)"><code><span style=
=3D"color:#606"></span><div><span style=3D"color:#606"><font style=3D"backg=
round-color:transparent" color=3D"rgb(34,34,34)" face=3D"Arial"><br>=C2=A0s=
truct A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=A0 int i =3D 1;<br>=C2=A0};</fo=
nt></span></div><div><br></div><div><span style=3D"color:#606"><font style=
=3D"background-color:transparent" color=3D"rgb(34,34,34)" face=3D"Arial">=
=C2=A0struct B : public A<br>=C2=A0{</font></span></div><div><br></div><div=
><span style=3D"color:#606"><font style=3D"background-color:transparent" co=
lor=3D"rgb(34,34,34)" face=3D"Arial">=C2=A0};<br>=C2=A0<br>int main() {<br>=
=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0 B b;<br>=C2=A0=C2=A0=C2=A0 auto i=
 =3D b.i;<br>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; i=
;<br>}</font></span><span style=3D"color:#660"></span></div></code><br></di=
v></div><div><br></div><div>And with=C2=A0the proposal:</div><div><br></div=
><div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;=
background-color:rgb(250,250,250)"><code><div><span style=3D"color:#606"><f=
ont style=3D"background-color:transparent" color=3D"rgb(34,34,34)" face=3D"=
Arial">=C2=A0struct A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=C2=A0 int i =3D 1;<b=
r>=C2=A0};</font></span></div><div><br></div><div><span style=3D"color:#606=
"><font style=3D"background-color:transparent" color=3D"rgb(34,34,34)" face=
=3D"Arial">=C2=A0struct B : public using A<br>=C2=A0{<br>=C2=A0=C2=A0=C2=A0=
=C2=A0 operator A&amp;() { return a; }<br>=C2=A0=C2=A0=C2=A0=C2=A0 A a;<br>=
=C2=A0};<br>=C2=A0<br>int main() {<br>=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=
=C2=A0 B b;<br>=C2=A0=C2=A0=C2=A0 auto i =3D b.i;<br>=C2=A0=C2=A0=C2=A0 <br=
>=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; i;<br>}</font></span><span style=3D"=
color:#660"></span></div></code></div><br></div><div><i>Does not look that =
bad at all -</i>=C2=A0You mix both to get the benefits of both! </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/74d6d50b-fe9e-4517-a18b-0316ffb96060%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/74d6d50b-fe9e-4517-a18b-0316ffb96060=
%40isocpp.org</a>.<br />

------=_Part_224_248488012.1476863230144--

------=_Part_223_375426593.1476863230143--

.