220 8740 <4ebf9705-9ed6-42fb-976c-3fdaf0f8c27f@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: Mon, 20 Jan 2014 05:30:32 -0800 (PST)
Lines: 224
Approved: news@gmane.org
Message-ID: <4ebf9705-9ed6-42fb-976c-3fdaf0f8c27f@isocpp.org>
References: <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> <52D9E336.1060801@knejp.de>
 <1B534FD7-B385-4A7E-A718-3C73F0AB61DC@gmail.com> <11f13f8f-1270-427c-8942-94027a181ff4@isocpp.org>
 <20140119174431.GA16875@faust.lysator.liu.se> <CAPOJ94Nt8tinr8hGeR-=rWZS0a529kY38NU-yo6BYM6kVo7czg@mail.gmail.com>
 <20140119192238.GA19497@faust.lysator.liu.se> <60842af6-5ec4-4364-b2d5-a0be9d578bd6@isocpp.org>
 <6c82c4ae-c144-443a-81b2-ea1a6b645601@isocpp.org> <CAGg_6+NYK0pndHN1sUk9=Lzz2gda_c5Yb1R_MXHXEPudwM5TmA@mail.gmail.com>
 <CANh-dXk8xb3aWcSr7qG75hjSNAu5hQR0EopiELSTdDLF-OjXuw@mail.gmail.com> <CAGg_6+OHw8jAO_m0Sj1GxkiB__mxPXfMDVh7tEiZsparxqi1HA@mail.gmail.com>
 <CANh-dXmQ7eqpzJqeXQsoYxZ3L221OfxegPySmZ3V0o0rhMsT9w@mail.gmail.com>
 <ed4130b2-902f-4400-bece-3a645dc39504@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; 
	boundary="----=_Part_8_1283287.1390224632687"
X-Trace: ger.gmane.org 1390224631 23218 80.91.229.3 (20 Jan 2014 13:30:31 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Mon, 20 Jan 2014 13:30:31 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDA3LUEAQACBB6OJ6SLAKGQEWGCIBPI@isocpp.org Mon Jan 20 14:30:39 2014
Return-path: <std-proposals+bncBDA3LUEAQACBB6OJ6SLAKGQEWGCIBPI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-vb0-f69.google.com ([209.85.212.69])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDA3LUEAQACBB6OJ6SLAKGQEWGCIBPI@isocpp.org>)
	id 1W5Evy-0007II-OI
	for gclcip-std-proposals@m.gmane.org; Mon, 20 Jan 2014 14:30:35 +0100
Original-Received: by mail-vb0-f69.google.com with SMTP id m10sf11633689vbh.0
        for <gclcip-std-proposals@m.gmane.org>; Mon, 20 Jan 2014 05:30:33 -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=0Onu2uBqXSMd8SvWCxgLeHKCGXp3ywSShRNeottyYJQ=;
        b=UqWrknWJelo3Fu3QtmhdkFa1wjvrdIEuXkRBM5j5tbPzrQX+Uj3zrxwTELIH3gHgrn
         f/F1XHheIPc5mqMe/Se4e9t2pmU1j7xNC+twwyRXX5z+wiA84R3VvCuK8mSEGyJIGOiv
         YFnFOsJSNzL4bTJ6U3bOnyMBhOe4rhrmp7VNFI2vr657U1QsugZERMl0kcwotCUYb1zM
         qVHSoLV434vx8+qkWWsqOyEHp0Jdf/jkXmCL+QXvpz+gdIoHkkEmsKo99QHj2LkXPLh/
         VBAwTOcOYW2N6hPVgS8aus4dxvN3jBQfBtYsAmHfXIeYPTeIHUbyHaKuqEx5xzlm6YCG
         faOA==
X-Gm-Message-State: ALoCoQlXgvX0D7+ED4XorFgwypbQHo1/uqUkEtHAVgtzXgKaR4BhslIt+9JZPZ5Wy6OLyJM0bm8O
X-Received: by 10.58.189.73 with SMTP id gg9mr893542vec.34.1390224633839;
        Mon, 20 Jan 2014 05:30:33 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.182.181.6 with SMTP id ds6ls972063obc.77.gmail; Mon, 20 Jan
 2014 05:30:33 -0800 (PST)
X-Received: by 10.182.142.38 with SMTP id rt6mr64164obb.10.1390224633231;
        Mon, 20 Jan 2014 05:30:33 -0800 (PST)
In-Reply-To: <ed4130b2-902f-4400-bece-3a645dc39504@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:8740
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/8740>

------=_Part_8_1283287.1390224632687
Content-Type: text/plain; charset=UTF-8



On Monday, January 20, 2014 6:15:16 AM UTC-6, Alexander Bolz wrote:
>
> Please let me summarize why I think string_view should be constructible
> from a nullptr (and a zero length) and and data() should return the
> pointer passed to the constructor. Please, if I got anything wrong, let me
> know! I really don't understand the reason for data() != null.
>
> The only reason presented here that data() should always return non-null is
> that "nullptrs are bad". I'm not convinced. If there are other arguments,
> I really would like to hear them.
>
> Since it's not null terminated, string_view's data() is not a replacement
> for string's data() and since it might contain null characters, string's
> data() is not a replacement for C-strings. When using data() I have to
> be careful anyway.
>
> data() == null (which implies size() == 0) doesn't force the user
> to write additional null checks. The standard _explicitly_ allows
> nullptr + 0 and nullptr - nullptr. So if I use any standard algorithm
> like find, I can write
>
> find(sv.data(), sv.data() + sv.size(), 'x')
>
> or
>
> find(sv.begin(), sv.end(), 'x').
>
> If a function f takes an iterator and and a length I could also write
>
> f(sv.begin(), sv.end() - sv.begin()).
>
> For all these algorithms using iterators, a null string_view is exactly
> the same as an empty string_view.
>
> Actually, allowing data() == null frees the user from performing null 
> checks.
>
> So I think allowing data() == null makes working with C-strings more safe
> and working with std::string's more efficient. And of course I can directly
> use any other contiguous range of characters as a (sub-)string.
>
> And if there are situations where I need/want to know whether a string_view
> was constructed from a nullptr, I can get this information, too.
>
> This would not (directly) be possible if string_view were constructible 
> from
> a nullptr, but the return value of data() is unspecified. It actually
> would introduce UB if I don't pay extra attention to this.
>
> void f(char const* ptr, size_t len)
> {
>     auto s = string_view(ptr, len);
>     // ...
>     g(ptr, s.data() - ptr);
> }
>
> Summary: I pay for what I don't use: a non-null ptr.
>
>
Thanks; that's a clear statement.  In return, here's my reasoning for the 
other perspective:

In addition to that it expresses something std::string cannot express, my 
main objection to allowing string_view(p) where p is a null pointer value 
is the assumption that this should be implicitly treated as identical to 
construction from an empty string.  I believe emptiness comes from 
size()==0, not from data()==nullptr in conjunction with an inference that 
therefore size() must also be zero because that's necessary to allow data() 
to be the basis of a valid range.

E.g., when getenv(3) returns a null pointer it means something very 
different from when it returns a non-null pointer to an empty string.  The 
argument that allowing null frees you from null checks only works when 
those two pointers signify the same thing and all uses of data() involve 
range operations.  It's equally true that disallowing null frees you from 
null checks because if you have a string_view at all you know data() cannot 
be null, and this becomes important when data() is being used as an 
iterator in its own right.

My strongest objection is to any line of reasoning that leads to:

  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(nullptr, sv.data());

passing in a conforming implementation due to an expectation that all empty 
ranges are equivalent.

Would it be acceptable to everybody if language were added to the proposal 
to the effect that all mutating string_view operations ensure that [data(), 
data()+size()) is a valid subrange of [bp, bp+bn) where [bp, bp+bn) 
identifies the range last assigned to the string_view (on construction, 
through assignment, or through clear())?

Is that even necessary?  I had thought it was the original intent and that 
the necessary language is already there, but I'm not convinced everybody 
else sees it that way, and that part of the reason is a belief in 
equivalence of empty ranges.

Or maybe I'm mistaken in my impression that some people don't accept the 
use of data() as an iterator outside the range of the string_view that 
returned it, a key capability that I believe the reference semantics of 
string_view must permit.

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_8_1283287.1390224632687
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Monday, January 20, 2014 6:15:16 AM UTC-6, Alex=
ander Bolz wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>Please let me summarize why I think string_view should be construc=
tible</div><div>from a nullptr (and a zero length) and and data() should re=
turn the</div><div>pointer passed to the constructor. Please, if I got anyt=
hing wrong, let me</div><div>know! I really don't understand the reason for=
 data() !=3D null.</div><div><br></div><div>The only reason presented here =
that data() should always return non-null is</div><div>that "nullptrs are b=
ad". I'm not convinced. If there are other arguments,</div><div>I really wo=
uld like to hear them.</div><div><br></div><div>Since it's not null termina=
ted, string_view's data() is not a replacement</div><div>for string's data(=
) and since it might contain null characters, string's</div><div>data() is =
not a replacement for C-strings. When using data() I have to</div><div>be c=
areful anyway.</div><div><br></div><div>data() =3D=3D null (which implies s=
ize() =3D=3D 0) doesn't force the user</div><div>to write additional null c=
hecks. The standard _explicitly_ allows</div><div>nullptr + 0 and nullptr -=
 nullptr. So if I use any standard algorithm</div><div>like find, I can wri=
te</div><div><br></div><div><font face=3D"courier new, monospace">find(sv.d=
ata(), sv.data() + sv.size(), 'x')</font></div><div><br></div><div>or</div>=
<div><br></div><div><font face=3D"courier new, monospace">find(sv.begin(), =
sv.end(), 'x').</font></div><div><br></div><div>If a function f takes an it=
erator and and a length I could also write</div><div><br></div><div><font f=
ace=3D"courier new, monospace">f(sv.begin(), sv.end() - sv.begin()).</font>=
</div><div><br></div><div>For all these algorithms using iterators, a null =
string_view is exactly</div><div>the same as an empty string_view.</div><di=
v><br></div><div>Actually, allowing data() =3D=3D null frees the user from =
performing null checks.</div><div><br></div><div>So I think allowing data()=
 =3D=3D null makes working with C-strings more safe</div><div>and working w=
ith std::string's more efficient. And of course I can directly</div><div>us=
e any other contiguous range of characters as a (sub-)string.</div><div><br=
></div><div>And if there are situations where I need/want to know whether a=
 string_view</div><div>was constructed from a nullptr, I can get this infor=
mation, too.</div><div><br></div><div>This would not (directly) be possible=
 if string_view were constructible from</div><div>a nullptr, but the return=
 value of data() is unspecified. It actually</div><div>would introduce UB i=
f I don't pay extra attention to this.</div><div><br></div><div><font face=
=3D"courier new, monospace">void f(char const* ptr, size_t len)</font></div=
><div><font face=3D"courier new, monospace">{</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; auto s =3D string_view(ptr, len);=
</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // ..=
..</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; g(pt=
r, s.data() - ptr);</font></div><div><font face=3D"courier new, monospace">=
}</font></div><div><br></div><div>Summary: I pay for what I don't use: a no=
n-null ptr.</div><div><br></div></div></blockquote><div><br>Thanks; that's =
a clear statement.&nbsp; In return, here's my reasoning for the other persp=
ective:<br><br>In addition to that it expresses something std::string canno=
t express, my main objection to allowing string_view(p) where p is a null p=
ointer value is the assumption that this should be implicitly treated as id=
entical to construction from an empty string.&nbsp; I believe emptiness com=
es from size()=3D=3D0, not from data()=3D=3Dnullptr in conjunction with an =
inference that therefore size() must also be zero because that's necessary =
to allow data() to be the basis of a valid range.<br><br>E.g., when getenv(=
3) returns a null pointer it means something very different from when it re=
turns a non-null pointer to an empty string.&nbsp; The argument that allowi=
ng null frees you from null checks only works when those two pointers signi=
fy the same thing and all uses of data() involve range operations.&nbsp; It=
's equally true that disallowing null frees you from null checks because if=
 you have a string_view at all you know data() cannot be null, and this bec=
omes important when data() is being used as an iterator in its own right.<b=
r><br>My strongest objection is to any line of reasoning that leads to:<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>&nbsp; ASSERT_EQ(0, sv.size());<br>&nbsp; ASSERT_EQ(nullptr, sv.dat=
a());<br><br>passing in a conforming implementation due to an expectation t=
hat all empty ranges are equivalent.<br><br>Would it be acceptable to every=
body if language were added to the proposal to the effect that all mutating=
 string_view operations ensure that [data(), data()+size()) is a valid subr=
ange of [bp, bp+bn) where [bp, bp+bn) identifies the range last assigned to=
 the string_view (on construction, through assignment, or through clear())?=
<br><br>Is that even necessary?&nbsp; I had thought it was the original int=
ent and that the necessary language is already there, but I'm not convinced=
 everybody else sees it that way, and that part of the reason is a belief i=
n equivalence of empty ranges.<br><br>Or maybe I'm mistaken in my impressio=
n that some people don't accept the use of data() as an iterator outside th=
e range of the string_view that returned it, a key capability that I believ=
e the reference semantics of string_view must permit.<br><br>Peter<br></div=
></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_8_1283287.1390224632687--

.
