[libcxx-commits] [libcxx] WIP [libc++][istream] P3223R2: Making `std::istream::ignore` less surprising (PR #147007)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Jul 5 23:09:34 PDT 2025
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/147007
>From 519cf0128796091eea589e8b8d925cd33ae503f1 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 07:57:26 +0300
Subject: [PATCH 1/7] [libc++][istream] P3223R2 Making `std::istream::ignore`
less surprising
Implements [P3223R2](https://wg21.link/P3223R2)
# References
- https://github.com/cplusplus/draft/pull/7996
---
libcxx/docs/ReleaseNotes/21.rst | 1 +
libcxx/include/istream | 8 ++++
.../ignore.char_type.pass.cpp | 41 +++++++++++++++++++
3 files changed, 50 insertions(+)
create mode 100644 libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index 08b32bb508dc1..34735ca515d53 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -51,6 +51,7 @@ Implemented Papers
- P2441R2: ``views::join_with`` (`Github <https://github.com/llvm/llvm-project/issues/105185>`__)
- P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github <https://github.com/llvm/llvm-project/issues/105252>`__)
- P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github <https://github.com/llvm/llvm-project/issues/105250>`__)
+- P3223R2: Making ``std::istream::ignore`` less surprising
Improvements and New Features
-----------------------------
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 02546902494e3..1343d2d81ac38 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -70,6 +70,7 @@ public:
basic_istream& getline(char_type* s, streamsize n, char_type delim);
basic_istream& ignore(streamsize n = 1, int_type delim = traits_type::eof());
+ basic_istream& ignore(streamsize n, char_type delim); // Since C++26
int_type peek();
basic_istream& read (char_type* s, streamsize n);
streamsize readsome(char_type* s, streamsize n);
@@ -291,6 +292,13 @@ public:
basic_istream& getline(char_type* __s, streamsize __n, char_type __dlm);
basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
+# if __LIBCPP_STD_VER >= 26
+ basic_istream& ignore(streamsize __n, char_type __delim)
+ requires is_same_v<char_type, char>
+ {
+ return ignore(__n, traits::to_int_type(__delim));
+ }
+# endif
int_type peek();
basic_istream& read(char_type* __s, streamsize __n);
streamsize readsome(char_type* __s, streamsize __n);
diff --git a/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
new file mode 100644
index 0000000000000..2074ecef0bd33
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// Requires 396145d in the built library.
+// XFAIL: using-built-library-before-llvm-9
+
+// <istream>
+
+// basic_istream& ignore(streamsize n, char_type delim);
+
+#include <cassert>
+#include <istream>
+#include <sstream>
+#include <string>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+ std::istringstream in("\xF0\x9F\xA4\xA1 Clown Face");
+ in.ignore(100, '\xA1'); // ignore up to '\xA1' delimiter,
+ // previously might have ignored to EOF
+
+ assert(in.gcount() == 4); // 4 bytes were ignored
+ assert(in.peek() == ' '); // next character is a space
+
+ std::string s1; // read the next word
+ in >> s1;
+ assert(s1 == "Clown");
+
+ in.ignore(100, -1L); // ambiguous overload,
+ // previously equivalent to (int)-1L
+
+ return 0;
+}
>From 40652b391f1d8ac11fb2f1599d8d36a00ed9b426 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 09:56:25 +0300
Subject: [PATCH 2/7] Some fixes
---
libcxx/include/istream | 17 +++++++++---
.../ignore.char_type.pass.cpp | 15 +++++------
.../istream.unformatted/ignore.verify.cpp | 27 +++++++++++++++++++
3 files changed, 47 insertions(+), 12 deletions(-)
create mode 100644 libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.verify.cpp
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 1343d2d81ac38..001fb91ec1b67 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -172,6 +172,7 @@ template <class Stream, class T>
# include <__type_traits/conjunction.h>
# include <__type_traits/enable_if.h>
# include <__type_traits/is_base_of.h>
+# include <__type_traits/is_same.h>
# include <__type_traits/make_unsigned.h>
# include <__utility/declval.h>
# include <__utility/forward.h>
@@ -292,11 +293,13 @@ public:
basic_istream& getline(char_type* __s, streamsize __n, char_type __dlm);
basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
-# if __LIBCPP_STD_VER >= 26
- basic_istream& ignore(streamsize __n, char_type __delim)
+# if _LIBCPP_STD_VER >= 26
+ // _LIBCPP_HIDE_FROM_ABI basic_istream& ignore(streamsize __n, char_type __delim)
+ // requires is_same_v<char_type, char>;
+ _LIBCPP_HIDE_FROM_ABI basic_istream& ignore(streamsize __n, char_type __delim)
requires is_same_v<char_type, char>
{
- return ignore(__n, traits::to_int_type(__delim));
+ return this->ignore(__n, _Traits::to_int_type(__delim));
}
# endif
int_type peek();
@@ -873,6 +876,14 @@ basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::ignore(streamsiz
return *this;
}
+// # if _LIBCPP_STD_VER >= 26
+// template <class _CharT, class _Traits>
+// basic_istream& basic_istream<_CharT, _Traits>&
+// basic_istream<_CharT, _Traits>::ignore(streamsize __n, char_type __delim) {
+// return this->ignore(__n, _Traits::to_int_type(__delim));
+// }
+// # endif
+
template <class _CharT, class _Traits>
typename basic_istream<_CharT, _Traits>::int_type basic_istream<_CharT, _Traits>::peek() {
ios_base::iostate __state = ios_base::goodbit;
diff --git a/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
index 2074ecef0bd33..6f3fe59c0cbc5 100644
--- a/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
@@ -25,17 +25,14 @@
int main(int, char**) {
std::istringstream in("\xF0\x9F\xA4\xA1 Clown Face");
in.ignore(100, '\xA1'); // ignore up to '\xA1' delimiter,
- // previously might have ignored to EOF
+ // previously might have ignored to EOF
- assert(in.gcount() == 4); // 4 bytes were ignored
- assert(in.peek() == ' '); // next character is a space
+ assert(in.gcount() == 4); // 4 bytes were ignored
+ assert(in.peek() == ' '); // next character is a space
- std::string s1; // read the next word
- in >> s1;
- assert(s1 == "Clown");
-
- in.ignore(100, -1L); // ambiguous overload,
- // previously equivalent to (int)-1L
+ std::string str; // read the next word
+ in >> str;
+ assert(str == "Clown");
return 0;
}
diff --git a/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.verify.cpp b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.verify.cpp
new file mode 100644
index 0000000000000..54d13cac69b94
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.verify.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// Requires 396145d in the built library.
+// XFAIL: using-built-library-before-llvm-9
+
+// <istream>
+
+// basic_istream& ignore(streamsize n, char_type delim);
+
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include "test_macros.h"
+
+void test() {
+ std::istringstream in("\xF0\x9F\xA4\xA1 Clown Face");
+ in.ignore(100, -1L); // expected-error {{call to member function 'ignore' is ambiguous}}
+}
>From b43663105bf89d8b2ca3235d0336d3ae9ac7b5ac Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 09:57:14 +0300
Subject: [PATCH 3/7] Cleanup
---
libcxx/include/istream | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 001fb91ec1b67..83ba1799cae91 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -294,8 +294,6 @@ public:
basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
# if _LIBCPP_STD_VER >= 26
- // _LIBCPP_HIDE_FROM_ABI basic_istream& ignore(streamsize __n, char_type __delim)
- // requires is_same_v<char_type, char>;
_LIBCPP_HIDE_FROM_ABI basic_istream& ignore(streamsize __n, char_type __delim)
requires is_same_v<char_type, char>
{
@@ -876,14 +874,6 @@ basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::ignore(streamsiz
return *this;
}
-// # if _LIBCPP_STD_VER >= 26
-// template <class _CharT, class _Traits>
-// basic_istream& basic_istream<_CharT, _Traits>&
-// basic_istream<_CharT, _Traits>::ignore(streamsize __n, char_type __delim) {
-// return this->ignore(__n, _Traits::to_int_type(__delim));
-// }
-// # endif
-
template <class _CharT, class _Traits>
typename basic_istream<_CharT, _Traits>::int_type basic_istream<_CharT, _Traits>::peek() {
ios_base::iostate __state = ios_base::goodbit;
>From bbaadc186854454e7da30c7b2d25c4a4d4e03ff0 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 10:04:24 +0300
Subject: [PATCH 4/7] Cleanup
---
.../input.streams/istream.unformatted/ignore.char_type.pass.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
index 6f3fe59c0cbc5..9d83a7ea15027 100644
--- a/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/input.streams/istream.unformatted/ignore.char_type.pass.cpp
@@ -16,7 +16,6 @@
// basic_istream& ignore(streamsize n, char_type delim);
#include <cassert>
-#include <istream>
#include <sstream>
#include <string>
>From 341fe8552378a0e6a601b1dd35400d726703571c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <zingam at outlook.com>
Date: Sat, 5 Jul 2025 08:05:53 +0300
Subject: [PATCH 5/7] Update libcxx/include/istream
---
libcxx/include/istream | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 83ba1799cae91..7f15c32f67b9c 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -294,7 +294,7 @@ public:
basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
# if _LIBCPP_STD_VER >= 26
- _LIBCPP_HIDE_FROM_ABI basic_istream& ignore(streamsize __n, char_type __delim)
+ basic_istream& ignore(streamsize __n, char_type __delim)
requires is_same_v<char_type, char>
{
return this->ignore(__n, _Traits::to_int_type(__delim));
>From 4cb58c00e1bd6fd967f94279ca03384675acc9ba Mon Sep 17 00:00:00 2001
From: Hristo Hristov <zingam at outlook.com>
Date: Sat, 5 Jul 2025 17:01:18 +0300
Subject: [PATCH 6/7] Update libcxx/include/istream
---
libcxx/include/istream | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 7f15c32f67b9c..7a3aa3d31a019 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -294,7 +294,7 @@ public:
basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
# if _LIBCPP_STD_VER >= 26
- basic_istream& ignore(streamsize __n, char_type __delim)
+ inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& ignore(streamsize __n, char_type __delim)
requires is_same_v<char_type, char>
{
return this->ignore(__n, _Traits::to_int_type(__delim));
>From 64bc4430d9bb581bd5a8882337b47cc45d314b1c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 6 Jul 2025 09:09:14 +0300
Subject: [PATCH 7/7] Try one last time
---
libcxx/include/istream | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/istream b/libcxx/include/istream
index 7a3aa3d31a019..83ba1799cae91 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -294,7 +294,7 @@ public:
basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
# if _LIBCPP_STD_VER >= 26
- inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& ignore(streamsize __n, char_type __delim)
+ _LIBCPP_HIDE_FROM_ABI basic_istream& ignore(streamsize __n, char_type __delim)
requires is_same_v<char_type, char>
{
return this->ignore(__n, _Traits::to_int_type(__delim));
More information about the libcxx-commits
mailing list