[libcxx-commits] [libcxx] 4be7f48 - [libc++] Implement P1391 for string_view
Joe Loser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Oct 6 11:19:05 PDT 2021
Author: Joe Loser
Date: 2021-10-06T14:17:10-04:00
New Revision: 4be7f48960980831a9b744c96f38ddb7dc7848ce
URL: https://github.com/llvm/llvm-project/commit/4be7f48960980831a9b744c96f38ddb7dc7848ce
DIFF: https://github.com/llvm/llvm-project/commit/4be7f48960980831a9b744c96f38ddb7dc7848ce.diff
LOG: [libc++] Implement P1391 for string_view
Implement P1391 (https://wg21.link/p1391) which allows
`std::string_view` to be constructible from any contiguous range of
characters.
Note that a different paper (http://wg21.link/P1989) handles the generic
range constructor for `std::string_view`.
Reviewed By: ldionne, Quuxplusone, Mordante, #libc
Differential Revision: https://reviews.llvm.org/D110718
Added:
libcxx/test/std/strings/string.view/string.view.cons/deduct.pass.cpp
libcxx/test/std/strings/string.view/string.view.cons/from_iterator_sentinel.pass.cpp
Modified:
libcxx/docs/Status/Cxx20Papers.csv
libcxx/include/string_view
libcxx/test/support/make_string.h
libcxx/test/support/test_iterators.h
Removed:
################################################################################
diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
index ee59d657b9f2..c722b9676b4a 100644
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -134,7 +134,7 @@
"`P1754 <https://wg21.link/P1754>`__","LWG","Rename concepts to standard_case for C++20, while we still can","Cologne","|In Progress|",""
"","","","","",""
"`P0883 <https://wg21.link/P0883>`__","LWG","Fixing Atomic Initialization","Belfast","|Complete| [#note-P0883]_","13.0"
-"`P1391 <https://wg21.link/P1391>`__","LWG","Range constructor for std::string_view","Belfast","* *",""
+"`P1391 <https://wg21.link/P1391>`__","LWG","Range constructor for std::string_view","Belfast","|Complete|","14.0"
"`P1394 <https://wg21.link/P1394>`__","LWG","Range constructor for std::span","Belfast","* *",""
"`P1456 <https://wg21.link/P1456>`__","LWG","Move-only views","Belfast","* *",""
"`P1622 <https://wg21.link/P1622>`__","LWG","Mandating the Standard Library: Clause 32 - Thread support library","Belfast","* *",""
diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index 33c8d6db7a1e..45bb7654930d 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -85,6 +85,8 @@ namespace std {
constexpr basic_string_view(const charT* str);
basic_string_view(nullptr_t) = delete; // C++2b
constexpr basic_string_view(const charT* str, size_type len);
+ template <class It, class End>
+ constexpr basic_string_view(It begin, End end); // C++20
// 7.4, basic_string_view iterator support
constexpr const_iterator begin() const noexcept;
@@ -166,6 +168,10 @@ namespace std {
size_type size_; // exposition only
};
+ // basic_string_view deduction guides
+ template<class It, class End>
+ basic_string_view(It, End) -> basic_string_view<iter_value_t<It>>; // C++20
+
// 7.11, Hash support
template <class T> struct hash;
template <> struct hash<string_view>;
@@ -185,6 +191,8 @@ namespace std {
*/
+#include <__concepts/convertible_to.h>
+#include <__concepts/same_as.h>
#include <__config>
#include <__debug>
#include <__ranges/enable_borrowed_range.h>
@@ -270,6 +278,16 @@ public:
#endif
}
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+ template <contiguous_iterator _It, sized_sentinel_for<_It> _End>
+ requires (same_as<iter_value_t<_It>, _CharT> && !convertible_to<_End, size_type>)
+ constexpr _LIBCPP_HIDE_FROM_ABI basic_string_view(_It __begin, _End __end)
+ : __data(_VSTD::to_address(__begin)), __size(__end - __begin)
+ {
+ _LIBCPP_ASSERT((__end - __begin) >= 0, "std::string_view::string_view(iterator, sentinel) received invalid range");
+ }
+#endif
+
_LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
basic_string_view(const _CharT* __s)
: __data(__s), __size(_VSTD::__char_traits_length_checked<_Traits>(__s)) {}
@@ -670,6 +688,13 @@ template <class _CharT, class _Traits>
inline constexpr bool ranges::enable_borrowed_range<basic_string_view<_CharT, _Traits> > = true;
#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+// [string.view.deduct]
+
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+template <contiguous_iterator _It, sized_sentinel_for<_It> _End>
+ basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>;
+#endif
+
// [string.view.comparison]
// operator ==
template<class _CharT, class _Traits>
diff --git a/libcxx/test/std/strings/string.view/string.view.cons/deduct.pass.cpp b/libcxx/test/std/strings/string.view/string.view.cons/deduct.pass.cpp
new file mode 100644
index 000000000000..f838fda8e262
--- /dev/null
+++ b/libcxx/test/std/strings/string.view/string.view.cons/deduct.pass.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <string_view>
+
+// template <contiguous_iterator _It, sized_sentinel_for<_It> _End>
+// basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>;
+
+#include <string_view>
+#include <cassert>
+
+#include "make_string.h"
+#include "test_macros.h"
+#include "test_iterators.h"
+
+template<class CharT, class Sentinel>
+constexpr void test() {
+ auto val = MAKE_STRING_VIEW(CharT, "test");
+ auto sv = std::basic_string_view(val.begin(), Sentinel(val.end()));
+ ASSERT_SAME_TYPE(decltype(sv), std::basic_string_view<CharT>);
+ assert(sv.size() == val.size());
+ assert(sv.data() == val.data());
+}
+
+constexpr void test() {
+ test<char, char*>();
+ test<wchar_t, wchar_t*>();
+ test<char8_t, char8_t*>();
+ test<char16_t, char16_t*>();
+ test<char32_t, char32_t*>();
+ test<char, const char*>();
+ test<char, sized_sentinel<const char*>>();
+}
+
+int main(int, char**) {
+ test();
+
+ return 0;
+}
+
diff --git a/libcxx/test/std/strings/string.view/string.view.cons/from_iterator_sentinel.pass.cpp b/libcxx/test/std/strings/string.view/string.view.cons/from_iterator_sentinel.pass.cpp
new file mode 100644
index 000000000000..a65ba2763e33
--- /dev/null
+++ b/libcxx/test/std/strings/string.view/string.view.cons/from_iterator_sentinel.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <string_view>
+
+// template <class It, class End>
+// constexpr basic_string_view(It begin, End end)
+
+#include <string_view>
+#include <cassert>
+#include <ranges>
+
+#include "make_string.h"
+#include "test_iterators.h"
+
+template<class CharT, class Sentinel>
+constexpr void test() {
+ auto val = MAKE_STRING_VIEW(CharT, "test");
+ auto sv = std::basic_string_view<CharT>(val.begin(), Sentinel(val.end()));
+ ASSERT_SAME_TYPE(decltype(sv), std::basic_string_view<CharT>);
+ assert(sv.size() == val.size());
+ assert(sv.data() == val.data());
+}
+
+constexpr bool test() {
+ test<char, char*>();
+ test<wchar_t, wchar_t*>();
+ test<char8_t, char8_t*>();
+ test<char16_t, char16_t*>();
+ test<char32_t, char32_t*>();
+ test<char, const char*>();
+ test<char, sized_sentinel<const char*>>();
+ return true;
+}
+
+static_assert( std::is_constructible_v<std::string_view, const char*, char*>);
+static_assert( std::is_constructible_v<std::string_view, char*, const char*>);
+static_assert(!std::is_constructible_v<std::string_view, char*, void*>); // not a sentinel
+static_assert(!std::is_constructible_v<std::string_view, signed char*, signed char*>); // wrong char type
+static_assert(!std::is_constructible_v<std::string_view, random_access_iterator<char*>, random_access_iterator<char*>>); // not contiguous
+static_assert( std::is_constructible_v<std::string_view, contiguous_iterator<char*>, contiguous_iterator<char*>>);
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
+
diff --git a/libcxx/test/support/make_string.h b/libcxx/test/support/make_string.h
index 5ffcd48c10f2..1ff3dc4e5211 100644
--- a/libcxx/test/support/make_string.h
+++ b/libcxx/test/support/make_string.h
@@ -16,6 +16,7 @@
#endif
#include <string>
+#include <string_view>
#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
#define CHAR8_ONLY(x) x,
@@ -56,6 +57,11 @@ struct MultiStringType {
static_cast<const CharT*>(MultiStringType MKSTR(Str)) \
}
+#define MAKE_STRING_VIEW(CharT, Str) \
+ std::basic_string_view<CharT> { \
+ static_cast<const CharT*>(MultiStringType MKSTR(Str)) \
+ }
+
// Like MAKE_STRING but converts to a const CharT*.
#define MAKE_CSTRING(CharT, Str) \
static_cast<const CharT*>(MultiStringType MKSTR(Str))
diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index f0e83b46aa63..d69ceec66066 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -885,6 +885,39 @@ class sentinel_wrapper {
I base_ = I();
};
+template <std::input_or_output_iterator I>
+class sized_sentinel {
+public:
+ sized_sentinel() = default;
+ constexpr explicit sized_sentinel(I base) : base_(std::move(base)) {}
+
+ constexpr bool operator==(const I& other) const requires std::equality_comparable<I> {
+ return base_ == other;
+ }
+
+ constexpr const I& base() const& { return base_; }
+ constexpr I base() && { return std::move(base_); }
+
+ template<std::input_or_output_iterator I2>
+ requires sentinel_for_base<I, I2>
+ constexpr bool operator==(const I2& other) const {
+ return base_ == other.base();
+ }
+
+private:
+ I base_ = I();
+};
+
+template <std::input_or_output_iterator I>
+constexpr auto operator-(sized_sentinel<I> sent, std::input_or_output_iterator auto iter) {
+ return sent.base() - iter;
+}
+
+template <std::input_or_output_iterator I>
+constexpr auto operator-(std::input_or_output_iterator auto iter, sized_sentinel<I> sent) {
+ return iter - sent.base();
+}
+
template <class It>
class three_way_contiguous_iterator
{
More information about the libcxx-commits
mailing list