220 8675 <e7b42a79-a1a6-4510-980c-a4b4ec3b950c@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: Peter Bigot <bigotp@acm.org>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: string_view::is_null()
Date: Fri, 17 Jan 2014 18:15:43 -0800 (PST)
Lines: 210
Approved: news@gmane.org
Message-ID: <e7b42a79-a1a6-4510-980c-a4b4ec3b950c@isocpp.org>
References: <8045a4d2-721d-4725-8bb7-7a91b6f53ec8@isocpp.org>
 <186E0927-C962-4E34-AED0-E7509DD1F0A0@gmail.com> <7aad44d8-6b4e-438a-b309-bd898b994b34@isocpp.org>
 <9C2C439F-7983-4224-B272-53CAD0E2E456@gmail.com> <CANh-dXnYg=1kmm1nJdSnTXmYyfBxbLTD9b+wecT+eZm5nPkf2A@mail.gmail.com>
 <CAGg_6+Pz0gQQcY_Vq6LTMFc-4iOJvVN1O3jc3gjh0J2egBTgGg@mail.gmail.com>
 <CANh-dX=Dr35_jvxadm2HWxNk6e87y8V+Dkyiw+syBfgfdTfobw@mail.gmail.com>
 <CAPOJ94O19N207rjm73tKJSc7K55kOzYxHbY9wtXquk=_uqqMsA@mail.gmail.com>
 <8E74B747-7450-41E0-8D1E-48C2D6F81535@gmail.com> <CAGNvRgDH=X2h4K_u3zOu7gUNuQbAcNHGNh=HfCRO9qG1mmiG1w@mail.gmail.com>
 <CANh-dXnytwWwS7E_BGA-xK8E-zw788TJKzM=HJdC-9JbF7+gTQ@mail.gmail.com> <104254A6-C69A-4571-8455-89D7E466D493@gmail.com>
 <CANh-dXngzdnwZZnLRxd=AXQcqLaQky9Cpdw6pkbH8tFqRyZavw@mail.gmail.com>
 <6a95bf9c-55c9-4ae2-966f-d1b1f4df6a37@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; 
	boundary="----=_Part_206_29211677.1390011343349"
X-Trace: ger.gmane.org 1390011340 4189 80.91.229.3 (18 Jan 2014 02:15:40 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Sat, 18 Jan 2014 02:15:40 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDA3LUEAQACBBUGH46LAKGQE3GSYQQI@isocpp.org Sat Jan 18 03:15:49 2014
Return-path: <std-proposals+bncBDA3LUEAQACBBUGH46LAKGQE3GSYQQI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-oa0-f69.google.com ([209.85.219.69])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDA3LUEAQACBBUGH46LAKGQE3GSYQQI@isocpp.org>)
	id 1W4LRp-00047S-MY
	for gclcip-std-proposals@m.gmane.org; Sat, 18 Jan 2014 03:15:45 +0100
Original-Received: by mail-oa0-f69.google.com with SMTP id h16sf16500413oag.4
        for <gclcip-std-proposals@m.gmane.org>; Fri, 17 Jan 2014 18:15:44 -0800 (PST)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe:content-type;
        bh=PEP3DX+xhhJ1r3Y22croObcfgwkPkgbtY4PLfjjQeFA=;
        b=fFaxpU/GCmm95LHCrPalKShy2nAkipubbxnZDi3ZQdMbji9i1p4s/Wr3qqWvzyL+HB
         j6gqOXK+UD0me5S+tLgpRIp3rGbQbpx+x1/6749r5+lLjSsLvrmz7YT5r0IsbagAjyLI
         SQFMSgkoOSsh54t+7e5P/9RKVxLLF7NBNaW3J6gueYDI3U8gd7nnYkhWjDLlSCQLw2g5
         W6+HxWdM5w1cUowuHoR36TC/RWRiCqszFCsVdBhQNZ3iUBc3Eyy1Fc9RDXj8PnYokDfh
         UPpbCQW38xq9hZJw008OVmH2vdXZMNS8PCfbx2Fas+jzyAGpqgCRAko5ZSzRWNA6wDBK
         SsvA==
X-Gm-Message-State: ALoCoQlBeuhk7WajnnuuCsM9aXPPFmDyN1hhp782md+0tNYczubG5yrkJJJRafth9rhD3+AaMPU7
X-Received: by 10.182.216.200 with SMTP id os8mr2078063obc.0.1390011344561;
        Fri, 17 Jan 2014 18:15:44 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.182.3.3 with SMTP id 3ls593652oby.95.gmail; Fri, 17 Jan 2014
 18:15:44 -0800 (PST)
X-Received: by 10.182.199.39 with SMTP id jh7mr1569obc.25.1390011344015;
        Fri, 17 Jan 2014 18:15:44 -0800 (PST)
In-Reply-To: <6a95bf9c-55c9-4ae2-966f-d1b1f4df6a37@isocpp.org>
X-Original-Sender: bigotp@acm.org
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:8675
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/8675>

------=_Part_206_29211677.1390011343349
Content-Type: text/plain; charset=UTF-8

On Friday, January 17, 2014 7:00:12 PM UTC-6, Bengt Gustafsson wrote:
>
> I have not followed this entire thread, instead I hacked up a little 
> implementation which I used in implementing something for another thread on 
> an improved "printf" functionality. What I noticed was:
>
> - I had use for a C array of string_view to keep the parts of the original 
> string that fell between each data inserted. This means that I must be able 
> to default construct string_view as there is no other way to construct an 
> array element.
>

Sure, that's one approach.
 

> - It is logical to do this default construction by setting m_begin and 
> m_end to nullptr, or m_begin to nullptr and m_size to 0.
>

Logical, perhaps; necessary, no.  It's equally or more logical to treat it 
the same as a default-constructed std::string.  It was tentatively agreed 
much earlier in this or another thread that doing so doesn't even require 
allocating any memory to hold the "referenced" empty string, while still 
preserving the requirement that data() have a value distinct from nullptr.
 

> - It must be allowed to take a default constructed string_view as the 
> range of a range based for statement
>

Sure.
 

> __or__ to check if the range is in default constucted state using 
> something like os_null().
>

Why?  Is there something specific to ranges that makes a 
default-constructed range significant?


> - both of these methods are impossible if the presumptions stated above 
> "begin() should never return nullptr" and "we don't need a special 
> is_null()". Well, not entirely. Of course you could create some bogus 
> object and use its address instead of nullptr.
>
> Someone stated above that the \0 at the end of the string should be 
> accessible even if the string_view is empty. This is clearly impossible as 
> a string_view may be constructed as a part of a string which continues on. 
> Thus there is no \0 at *end() anytime.
>

This may be referring to what I said about deref(sv2) in Marshall's 
example, but if so it isn't an accurate summary.  What I said is that if a 
string_view is constructed from a string literal (which is necessarily 
nul-terminated) and the default size calculated from traits::length(str), 
then even though accessing the terminating nul from the string_view is not 
legal the nul is still there and still legally accessible by using a char* 
pointer which is known to point into that string literal.

Here's another example which avoids the nul and any assumptions about 
persistence of the string literal:

  const std::string base("ABCDE");
  string_view sv(base);
  ASSERT_EQ(base.data(), sv.data());
  sv.remove_prefix(2);
  ASSERT_EQ(base.data()+2, sv.data());
  sv.remove_suffix(3);
  ASSERT_EQ(0, sv.size());
  ASSERT_EQ(base.data()+2, sv.data());
  ASSERT_EQ('C', *sv.data());

sv in isolation only guarantees that [sv.data(), sv.data()+0) is a valid 
range and specifically does not sanction the expression *sv.data().

But sv.data() is value- and type-equivalent to base.data()+2 by the 
specification for string_view.

And accessing *(base.data()+2) is perfectly legitimate.

So why can't I substitute a value- and type-equivalent subexpression into 
that dereference expression?

I'm hoping that somebody will explain why this is an invalid use of 
std::string_view as currently described in 
https://rawgithub.com/google/cxx-std-draft/string-ref-paper/string_view.html.

As for why I think allowing null sv.data() creates a new requirement to 
check for null sv.data():  If you accept that sv.data() can be useful even 
though sv.size() is zero---perhaps for nothing more than to calculate an 
offset into the original string with sv.data()-base.data()---then it 
becomes necessary to know that sv.data() is not null regardless of whether 
sv.size() is zero so you don't perform pointer arithmetic on a null 
pointer.  Not always, but certainly if you're using sv.data() this way 
(which I have found very convenient).

My preference is to impose the non-null requirement on the string_view type 
just as it is imposed on std::string, rather than have to check it 
manually.   (AFAIK std::string has never permitted its data() function to 
return a null pointer, so I don't see a lot of value in reviewing that 
decision.)

Peter

-- 

--- 
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_206_29211677.1390011343349
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, January 17, 2014 7:00:12 PM UTC-6, Bengt Gustaf=
sson 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 =
have not followed this entire thread, instead I hacked up a little implemen=
tation which I used in implementing something for another thread on an impr=
oved "printf" functionality. What I noticed was:<div><br></div><div>- I had=
 use for a C array of string_view to keep the parts of the original string =
that fell between each data inserted. This means that I must be able to def=
ault construct string_view as there is no other way to construct an array e=
lement.</div></div></blockquote><div><br>Sure, that's one approach.<br>&nbs=
p;<br></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>- It is logical to do this default construction by setting m_begin and =
m_end to nullptr, or m_begin to nullptr and m_size to 0.</div></div></block=
quote><div><br>Logical, perhaps; necessary, no.&nbsp; It's equally or more =
logical to treat it the same as a default-constructed std::string.&nbsp; It=
 was tentatively agreed much earlier in this or another thread that doing s=
o doesn't even require allocating any memory to hold the "referenced" empty=
 string, while still preserving the requirement that data() have a value di=
stinct from nullptr.<br>&nbsp;<br></div><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>- It must be allowed to take a default cons=
tructed string_view as the range of a range based for statement</div></div>=
</blockquote><div><br>Sure.<br>&nbsp;<br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div> __or__ to check if the range is in =
default constucted state using something like os_null().</div></div></block=
quote><div><br>Why?&nbsp; Is there something specific to ranges that makes =
a default-constructed range significant?<br></div><div><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>- b=
oth of these methods are impossible if the presumptions stated above "begin=
() should never return nullptr" and "we don't need a special is_null()". We=
ll, not entirely. Of course you could create some bogus object and use its =
address instead of nullptr.</div><div><br></div><div>Someone stated above t=
hat the \0 at the end of the string should be accessible even if the string=
_view is empty. This is clearly impossible as a string_view may be construc=
ted as a part of a string which continues on. Thus there is no \0 at *end()=
 anytime.</div></div></blockquote><div><br>This may be referring to what I =
said about deref(sv2) in Marshall's example, but if so it isn't an accurate=
 summary.&nbsp; What I said is that if a string_view is constructed from a =
string literal (which is necessarily nul-terminated) and the default size c=
alculated from traits::length(str), then even though accessing the terminat=
ing nul from the string_view is not legal the nul is still there and still =
legally accessible by using a char* pointer which is known to point into th=
at string literal.<br></div><br>Here's another example which avoids the nul=
 and any assumptions about persistence of the string literal:<br><br>&nbsp;=
 const std::string base("ABCDE");<br>&nbsp; string_view sv(base);<br>&nbsp;=
 ASSERT_EQ(base.data(), sv.data());<br>&nbsp; sv.remove_prefix(2);<br>&nbsp=
; ASSERT_EQ(base.data()+2, sv.data());<br>&nbsp; sv.remove_suffix(3);<br>&n=
bsp; ASSERT_EQ(0, sv.size());<br>&nbsp; ASSERT_EQ(base.data()+2, sv.data())=
;<br>&nbsp; ASSERT_EQ('C', *sv.data());<br><br>sv in isolation only guarant=
ees that [sv.data(), sv.data()+0) is a valid range and specifically does no=
t sanction the expression *sv.data().<br><br>But sv.data() is value- and ty=
pe-equivalent to base.data()+2 by the specification for string_view.<br><br=
>And accessing *(base.data()+2) is perfectly legitimate.<br><br>So why can'=
t I substitute a value- and type-equivalent subexpression into that derefer=
ence expression?<br><br>I'm hoping that somebody will explain why this is a=
n invalid use of std::string_view as currently described in https://rawgith=
ub.com/google/cxx-std-draft/string-ref-paper/string_view.html.<br><br>As fo=
r why I think allowing null sv.data() creates a new requirement to check fo=
r null sv.data():&nbsp; If you accept that sv.data() can be useful even tho=
ugh sv.size() is zero---perhaps for nothing more than to calculate an offse=
t into the original string with sv.data()-base.data()---then it becomes nec=
essary to know that sv.data() is not null regardless of whether sv.size() i=
s zero so you don't perform pointer arithmetic on a null pointer.&nbsp; Not=
 always, but certainly if you're using sv.data() this way (which I have fou=
nd very convenient).<br><br>My preference is to impose the non-null require=
ment on the string_view type just as it is imposed on std::string, rather t=
han have to check it manually.&nbsp;&nbsp; (AFAIK std::string has never per=
mitted its data() function to return a null pointer, so
 I don't see a lot of value in reviewing that decision.)<br><br>Peter<br></=
div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_206_29211677.1390011343349--

.
