forked from lwg/issues
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automatic update from GitHub Actions workflow
- Loading branch information
github-actions
committed
Nov 25, 2023
1 parent
dc9db4a
commit d79f5b7
Showing
22 changed files
with
490 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" | ||
"http://www.w3.org/TR/html4/strict.dtd"> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Issue 4017: Behavior of std::views::split on an empty range</title> | ||
<style type="text/css"> | ||
p {text-align:justify} | ||
li {text-align:justify} | ||
blockquote.note | ||
{ | ||
background-color:#E0E0E0; | ||
padding-left: 15px; | ||
padding-right: 15px; | ||
padding-top: 1px; | ||
padding-bottom: 1px; | ||
} | ||
ins {background-color:#A0FFA0} | ||
del {background-color:#FFA0A0} | ||
table {border-collapse: collapse;} | ||
@media (prefers-color-scheme: dark) { | ||
html { | ||
color: #ddd; | ||
background-color: black; | ||
} | ||
ins { | ||
background-color: #225522 | ||
} | ||
del { | ||
background-color: #662222 | ||
} | ||
a { | ||
color: #6af | ||
} | ||
a:visited { | ||
color: #6af | ||
} | ||
blockquote.note | ||
{ | ||
background-color: rgba(255, 255, 255, .10) | ||
} | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<hr> | ||
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#New">New</a> status.</em></p> | ||
<h3><a name="4017" href="lwg-active.html#4017">4017</a>. Behavior of <tt>std::views::split</tt> on an empty range</h3> | ||
<p><b>Section:</b> 26.7.17.3 <a href="https://wg21.link/range.split.iterator">[range.split.iterator]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> | ||
<b>Submitter:</b> Barry Revzin <b>Opened:</b> 2023-11-19 <b>Last modified:</b> 2023-11-25</p> | ||
<p><b>Priority: </b>Not Prioritized | ||
</p> | ||
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p> | ||
<p><b>Discussion:</b></p> | ||
<p> | ||
Consider the following example (which uses <tt>fmt::println</tt> instead of <tt>std::println</tt>, | ||
but they do the same thing in C++23): | ||
</p> | ||
<blockquote><pre> | ||
#include <iostream> | ||
#include <string> | ||
#include <ranges> | ||
#include <fmt/ranges.h> | ||
|
||
int main() | ||
{ | ||
fmt::println("{}", std::views::split(std::string(" x "), ' ')); | ||
fmt::println("{}", std::views::split(std::string(" "), ' ')); | ||
fmt::println("{}", std::views::split(std::string("x"), ' ')); | ||
fmt::println("{}", std::views::split(std::string(""), ' ')); | ||
} | ||
</pre></blockquote> | ||
<p> | ||
The output of this program (as specified today) is | ||
</p> | ||
<blockquote><pre> | ||
[[], ['x'], []] | ||
[[], []] | ||
[['x']] | ||
[] | ||
</pre></blockquote> | ||
<p> | ||
The principle set out in LWG <a href="lwg-defects.html#3478">3478</a> is that splitting a sequence containing <tt>N</tt> | ||
delimiters should lead to <tt>N+1</tt> subranges. That principle was broken if the <tt>N</tt>-th | ||
delimiter was at the end of the sequence, which was fixed by <a href="https://wg21.link/P2210">P2210</a>. | ||
<p/> | ||
However, the principle is still broken if the sequence contains zero delimiters. A non-empty sequence | ||
will split into one range, but an empty sequence will split into zero ranges. That last line is incorrect | ||
— splitting an empty range on a delimiter should yield a range of an empty range — not | ||
simply an empty range. | ||
<p/> | ||
Proposed Resolution: Currently, <tt>split_view::iterator</tt>'s constructor unconditionally initializes | ||
<tt><i>trailing_empty_</i></tt> to <tt>false</tt>. Instead, change 26.7.17.3 <a href="https://wg21.link/range.split.iterator">[range.split.iterator]</a>/1 | ||
to initialize <tt><i>trailing_empty_</i></tt> to <tt><i>cur_</i> == <i>next_</i>.begin()</tt> (i.e. | ||
<tt><i>trailing_empty_</i></tt> is typically <tt>false</tt>, but if we're empty on initialization then we | ||
have to have a trailing empty range). | ||
<p/> | ||
The following demo shows my implementation from <a href="https://wg21.link/P2210">P2210</a>, adjusted to fix this: | ||
<a href="https://godbolt.org/z/axWb64j9f">godbolt.org/z/axWb64j9f</a> | ||
</p> | ||
|
||
|
||
<p id="res-4017"><b>Proposed resolution:</b></p> | ||
<p> | ||
This wording is relative to <a href="https://wg21.link/N4964">N4964</a>. | ||
</p> | ||
|
||
<ol> | ||
|
||
<li><p>Modify 26.7.17.3 <a href="https://wg21.link/range.split.iterator">[range.split.iterator]</a> as indicated:</p> | ||
|
||
<blockquote> | ||
<pre> | ||
constexpr <i>iterator</i>(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next); | ||
</pre> | ||
<blockquote> | ||
<p> | ||
-1- <i>Effects</i>: Initializes <tt><i>parent_</i></tt> with <tt>addressof(parent)</tt>, <tt><i>cur_</i></tt> with | ||
<tt>std::move(current)</tt>, <del>and</del> <tt><i>next_</i></tt> with <tt>std::move(next)</tt><ins>, and | ||
<tt><i>trailing_empty_</i></tt> with <tt><i>cur_</i> == <i>next_</i>.begin()</tt></ins>. | ||
</p> | ||
</blockquote> | ||
</blockquote> | ||
</li> | ||
|
||
</ol> | ||
|
||
|
||
|
||
|
||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.