Why isn't there a std::string_view(const char*, const char*) constructor

85 views
Skip to first unread message

frr...@gmail.com

unread,
Apr 9, 2018, 11:13:44 PM4/9/18
to ISO C++ Standard - Discussion
Hello,

I was surprised to see that std::string_view does not have a constructor that takes a begin/end pointer on the underlying character array. This looks like an obvious feature, so I was wondering why it was left out.

This constructor is very useful in various string related algorithms, for example, splitting on a delimiter:

auto comma_pos = std::find(str.begin(), str.end(), ',');
if (comma_pos == str.end())
    throw ...;

std::pair<std::string_view, std::string_view> splitted{{str.begin(), comma_pos},
{comma_pos + 1, str.end()}};

Without this constructor, we have to compute the string string length by using end_ptr - begin_ptr for the second argument, which repeats the first argument needlessly.

Was there a good rationale for omitting this constructor ? If that was an oversight I'd be willing to write a quick paper to try to have that added.

Cheers,

Maxime.

Andrey Semashev

unread,
Apr 10, 2018, 3:59:00 AM4/10/18
to std-dis...@isocpp.org
On 04/10/18 06:13, frr...@gmail.com wrote:
> Hello,
>
> I was surprised to see that std::string_view does not have a constructor
> that takes a begin/end pointer on the underlying character array. This
> looks like an obvious feature, so I was wondering why it was left out.
>
> Was there a good rationale for omitting this constructor ?

string_view requires a contiguous array of characters and the
constructor from two iterators or pointers does not guarantee that.

Richard Hodges

unread,
Apr 10, 2018, 4:01:06 AM4/10/18
to std-dis...@isocpp.org
so does std::vector, std::string, etc.

That doesn't explain it.

 


--

--- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

Andrey Semashev

unread,
Apr 10, 2018, 4:09:25 AM4/10/18
to std-dis...@isocpp.org
On 04/10/18 11:01, Richard Hodges wrote:
>
>
> On 10 April 2018 at 09:58, Andrey Semashev <andrey....@gmail.com
> <mailto:andrey....@gmail.com>> wrote:
>
> On 04/10/18 06:13, frr...@gmail.com <mailto:frr...@gmail.com> wrote:
>
> Hello,
>
> I was surprised to see that std::string_view does not have a
> constructor that takes a begin/end pointer on the underlying
> character array. This looks like an obvious feature, so I was
> wondering why it was left out.
>
> Was there a good rationale for omitting this constructor ?
>
>
> string_view requires a contiguous array of characters and the
> constructor from two iterators or pointers does not guarantee that.
>
>
> so does std::vector, std::string, etc.
>
> That doesn't explain it.

The containers copy the data to internal storage. The source is not
required to be contiguous. String_view instead adopts the source.

Richard Hodges

unread,
Apr 10, 2018, 4:10:59 AM4/10/18
to std-dis...@isocpp.org
On Tue, 2018-04-10 at 11:09 +0300, Andrey Semashev wrote:
> On 04/10/18 11:01, Richard Hodges wrote:
> >
> >
> > On 10 April 2018 at 09:58, Andrey Semashev <andrey.semashev@gmail.c
> > om
> > <mailto:andrey....@gmail.com>> wrote:
> >
> > On 04/10/18 06:13, frr...@gmail.com <mailto:frr...@gmail.com>
> > wrote:
> >
> > Hello,
> >
> > I was surprised to see that std::string_view does not have
> > a
> > constructor that takes a begin/end pointer on the
> > underlying
> > character array. This looks like an obvious feature, so I
> > was
> > wondering why it was left out.
> >
> > Was there a good rationale for omitting this constructor ?
> >
> >
> > string_view requires a contiguous array of characters and the
> > constructor from two iterators or pointers does not guarantee
> > that.
> >
> >
> > so does std::vector, std::string, etc.
> >
> > That doesn't explain it.
>
> The containers copy the data to internal storage. The source is not
> required to be contiguous. String_view instead adopts the source.

OK, that makes more sense. Thank you.

>
signature.asc

Adam Badura

unread,
Apr 10, 2018, 4:32:16 AM4/10/18
to ISO C++ Standard - Discussion
> > string_view requires a contiguous array of characters and the
> > constructor from two iterators or pointers does not guarantee that.
> >
> >
> > so does std::vector, std::string, etc.
> >
> > That doesn't explain it.

> The containers copy the data to internal storage. The source is not
> required to be contiguous. String_view instead adopts the source.

std::vector and std::string in their iterator range constructors indeed do not require contiguous memory. But the iterators have to come from the same range. Which in case of pointers means (I think) they must come from single array. Which then means (AFAIK) that they do point to contiguous memory.

And the iterator range constructors do exist even though they cannot ensure the iterators come from the same range.

I'm also surprised with lack of the mentioned constructor.

Adam Badura

Thiago Macieira

unread,
Apr 10, 2018, 10:29:27 AM4/10/18
to std-dis...@isocpp.org
In what way is a pair of pointers not a contiguous array? If you iterate over
it, you're doing so contiguously.

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



Nevin Liber

unread,
Apr 10, 2018, 10:45:13 AM4/10/18
to std-dis...@isocpp.org
On Tue, Apr 10, 2018 at 9:29 AM, Thiago Macieira <thi...@macieira.org> wrote:
In what way is a pair of pointers not a contiguous array?

Contiguity is a runtime property, not a compile time property.

For instance, the range string1.data()..string2.data() is not a contiguous range.
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com>  +1-847-691-1404

Nicol Bolas

unread,
Apr 10, 2018, 10:57:29 AM4/10/18
to ISO C++ Standard - Discussion


On Tuesday, April 10, 2018 at 10:45:13 AM UTC-4, Nevin ":-)" Liber wrote:
On Tue, Apr 10, 2018 at 9:29 AM, Thiago Macieira <thi...@macieira.org> wrote:
In what way is a pair of pointers not a contiguous array?

Contiguity is a runtime property, not a compile time property.

For instance, the range string1.data()..string2.data() is not a contiguous range.

True, but the same would be true for `list1.begin(), list2.end()`. The point is that we already have interfaces that say "if the given iterators don't form a valid range, UB results". There's no reason not to do it here.

This argument makes even less sense in light of the fact that `span` has a two-pointer constructor.

The main issue with the OP's problem is that `string::iterator` isn't a pointer, so even with a two-pointer constructor, it wouldn't work. Not without a way to:

1: Compile-time verify that a particular iterator type is a contiguous iterator.
2: Runtime-convert a contiguous iterator to a pointer, without having to do `std::addressof(*it)`, which is not legal for end iterators.

Andrey Semashev

unread,
Apr 10, 2018, 11:13:45 AM4/10/18
to std-dis...@isocpp.org
On 04/10/18 17:57, Nicol Bolas wrote:
>
>
> On Tuesday, April 10, 2018 at 10:45:13 AM UTC-4, Nevin ":-)" Liber wrote:
>
> On Tue, Apr 10, 2018 at 9:29 AM, Thiago Macieira
> <thi...@macieira.org> wrote:
>
> In what way is a pair of pointers not a contiguous array?
>
>
> Contiguity is a runtime property, not a compile time property.
>
> For instance, the range string1.data()..string2.data() is not a
> contiguous range.
>
>
> True, but the same would be true for `list1.begin(), list2.end()`. The
> point is that we already have interfaces that say "if the given
> iterators don't form a valid range, UB results". There's no reason not
> to do it here.

I think the main difference stems from the common practice, where a
pointer + length indicates a contiguous range and a pair of iterators
(even if those happen to be pointers) - not necessarily so. We can argue
on whether this is a misconception or not, but at least that's the first
impression I get when I look at the code like that.

> This argument makes even less sense in light of the fact that `span`
> /has/ a two-pointer constructor.

I'm not familiar with span, but isn't it just another name for
boost::iterator_range? In that case, iterator_range does not need a
contiguous range and it is entirely possible and makes sense to have a
constructor from two iterators.

Thiago Macieira

unread,
Apr 10, 2018, 11:20:03 AM4/10/18
to std-dis...@isocpp.org
On Tuesday, 10 April 2018 08:13:41 PDT Andrey Semashev wrote:
> I think the main difference stems from the common practice, where a
> pointer + length indicates a contiguous range and a pair of iterators
> (even if those happen to be pointers) - not necessarily so. We can argue
> on whether this is a misconception or not, but at least that's the first
> impression I get when I look at the code like that.

I disagree. A pair of pointers whose relationship is unclear could be
anything. But a pair of pointers as a begin-end pair of an iterator range is
contiguous by definition.

> > This argument makes even less sense in light of the fact that `span`
> > /has/ a two-pointer constructor.
>
> I'm not familiar with span, but isn't it just another name for
> boost::iterator_range? In that case, iterator_range does not need a
> contiguous range and it is entirely possible and makes sense to have a
> constructor from two iterators.

An iterator range with non-pointer iterators does not imply contiguous range.
A range with pointers does.

Andrey Semashev

unread,
Apr 10, 2018, 11:24:29 AM4/10/18
to std-dis...@isocpp.org
On 04/10/18 18:19, Thiago Macieira wrote:
> On Tuesday, 10 April 2018 08:13:41 PDT Andrey Semashev wrote:
>> I think the main difference stems from the common practice, where a
>> pointer + length indicates a contiguous range and a pair of iterators
>> (even if those happen to be pointers) - not necessarily so. We can argue
>> on whether this is a misconception or not, but at least that's the first
>> impression I get when I look at the code like that.
>
> I disagree. A pair of pointers whose relationship is unclear could be
> anything. But a pair of pointers as a begin-end pair of an iterator range is
> contiguous by definition.

Yes, likely. But you'd have to ensure that the iterators are pointers
first, which may not be obvious. By default you have to assume the worst.

Richard Smith

unread,
Apr 10, 2018, 11:36:41 AM4/10/18
to std-dis...@isocpp.org
This line of reasoning seems entirely spurious to me. string_view and span should be constructible from any pair of contiguous iterators with the right value type. My understanding (from talking to a few LWG folks) is that these constructors are only missing because we don't yet have traits to detect contiguous iterators.

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.

Thiago Macieira

unread,
Apr 10, 2018, 11:53:16 AM4/10/18
to std-dis...@isocpp.org
On Tuesday, 10 April 2018 08:36:25 PDT Richard Smith wrote:
> This line of reasoning seems entirely spurious to me. string_view and span
> should be constructible from any pair of contiguous iterators with the
> right value type. My understanding (from talking to a few LWG folks) is
> that these constructors are only missing because we don't yet have traits
> to detect contiguous iterators.

That makes sense.

We could have added pointer-pair constructors, but instead we're holding out
for the iterator-pair when we have the trait available.

Tony V E

unread,
Apr 10, 2018, 12:10:59 PM4/10/18
to std-discussion
On Tue, Apr 10, 2018 at 11:53 AM, Thiago Macieira <thi...@macieira.org> wrote:
On Tuesday, 10 April 2018 08:36:25 PDT Richard Smith wrote:
> This line of reasoning seems entirely spurious to me. string_view and span
> should be constructible from any pair of contiguous iterators with the
> right value type. My understanding (from talking to a few LWG folks) is
> that these constructors are only missing because we don't yet have traits
> to detect contiguous iterators.

That makes sense.

We could have added pointer-pair constructors, but instead we're holding out
for the iterator-pair when we have the trait available.


But surely a pair of pointers will be detected as contiguous iterators, so we could add the pointer constructors now (as span appears to be doing).
Then add a generic constructor later.

--
Be seeing you,
Tony

frr...@gmail.com

unread,
Apr 10, 2018, 6:23:19 PM4/10/18
to ISO C++ Standard - Discussion


On Wednesday, 11 April 2018 00:57:29 UTC+10, Nicol Bolas wrote:
The main issue with the OP's problem is that `string::iterator` isn't a pointer, so even with a two-pointer constructor, it wouldn't work.

 There is no std::string in my post, str is supposed to be a string_view, sorry for the confusion.
Reply all
Reply to author
Forward
0 new messages