[libcxx-commits] [libcxx] [libc++][ranges] add static_assert for ranges::to (PR #135802)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Apr 20 10:13:33 PDT 2025
https://github.com/Yuzhiy05 updated https://github.com/llvm/llvm-project/pull/135802
>From 7515cdb203f3c2f1c0734c68de8e6b05d4573655 Mon Sep 17 00:00:00 2001
From: ImoutoCon1999 <ImoutoCon1999 at outlook.com>
Date: Tue, 15 Apr 2025 23:36:08 +0800
Subject: [PATCH 1/6] [libc++][ranges]add static_assert for ranges::to
---
libcxx/include/__ranges/to.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h
index c937b0656de87..2adae5e0edbfb 100644
--- a/libcxx/include/__ranges/to.h
+++ b/libcxx/include/__ranges/to.h
@@ -28,6 +28,8 @@
#include <__type_traits/add_pointer.h>
#include <__type_traits/is_const.h>
#include <__type_traits/is_volatile.h>
+#include <__type_traits/is_class.h>
+#include <__type_traits/is_union.h>
#include <__type_traits/type_identity.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
@@ -81,7 +83,7 @@ template <class _Container, input_range _Range, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
-
+ static_assert(is_class_v<_Container>||is_union_v<_Container>, "The target must be a class type");
// First see if the non-recursive case applies -- the conversion target is either:
// - a range with a convertible value type;
// - a non-range type which might support being created from the input argument(s) (e.g. an `optional`).
@@ -208,7 +210,7 @@ template <class _Container, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
-
+ static_assert(is_class_v<_Container>||is_union_v<_Container>, "The target must be a class type");
auto __to_func = []<input_range _Range, class... _Tail>(_Range&& __range, _Tail&&... __tail) static
requires requires { //
/**/ ranges::to<_Container>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...);
>From 44d6a6533fbc22e9dcbc2899ef631c0700564440 Mon Sep 17 00:00:00 2001
From: ImoutoCon1999 <ImoutoCon1999 at outlook.com>
Date: Tue, 15 Apr 2025 23:47:10 +0800
Subject: [PATCH 2/6] [libc++][ranges]test: add static_assert verification for
ranges::to
---
.../range.utility.conv/to.verfiy.cpp | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp
diff --git a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp
new file mode 100644
index 0000000000000..9ff01b10a759d
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp
@@ -0,0 +1,17 @@
+#include <ranges>
+
+
+
+void test(){
+ struct R {
+ int* begin() const{reurn nullptr;};
+ int* end() const{return nullptr;};
+
+ operator int() const { return 0; }
+ };
+ (void)std::ranges::to<int>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<int>());
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+
+}
\ No newline at end of file
>From 7fe72642b7e7f1860673ec5364366ab91dde75ab Mon Sep 17 00:00:00 2001
From: ImoutoCon1999 <ImoutoCon1999 at outlook.com>
Date: Wed, 16 Apr 2025 18:50:11 +0800
Subject: [PATCH 3/6] format added file and correct name
---
.../range.utility.conv/to.verfiy.cpp | 17 -----------------
.../range.utility.conv/to.verify.cpp | 15 +++++++++++++++
2 files changed, 15 insertions(+), 17 deletions(-)
delete mode 100644 libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
diff --git a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp
deleted file mode 100644
index 9ff01b10a759d..0000000000000
--- a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verfiy.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <ranges>
-
-
-
-void test(){
- struct R {
- int* begin() const{reurn nullptr;};
- int* end() const{return nullptr;};
-
- operator int() const { return 0; }
- };
- (void)std::ranges::to<int>(R{});
- //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)(R{} | std::ranges::to<int>());
- //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
-
-}
\ No newline at end of file
diff --git a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
new file mode 100644
index 0000000000000..01d211df340c4
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
@@ -0,0 +1,15 @@
+#include <ranges>
+
+void test() {
+ struct R {
+ int* begin() const { reurn nullptr; };
+ int* end() const { return nullptr; };
+
+ operator int() const { return 0; }
+ };
+ (void)std::ranges::to<int>(R{});
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<int>());
+ //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+
+}
\ No newline at end of file
>From f2c50573773471d35bffb4214117d21c7075d737 Mon Sep 17 00:00:00 2001
From: ImoutoCon1999 <ImoutoCon1999 at outlook.com>
Date: Wed, 16 Apr 2025 19:33:45 +0800
Subject: [PATCH 4/6] add banner
---
.../range.utility/range.utility.conv/to.verify.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
index 01d211df340c4..8e047f9cddf7b 100644
--- a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
@@ -1,3 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20
+
+
+// Test that the "mandates" requirements on the given class are checked using `static_assert`.
#include <ranges>
void test() {
>From ec5c94ad2fd5423d260775e48546436a6c605cb1 Mon Sep 17 00:00:00 2001
From: ImoutoCon1999 <ImoutoCon1999 at outlook.com>
Date: Wed, 16 Apr 2025 23:59:55 +0800
Subject: [PATCH 5/6] format file and test for other type be rejected
---
libcxx/include/__ranges/to.h | 8 +--
.../range.utility.conv/to.verify.cpp | 68 ++++++++++++++++---
2 files changed, 64 insertions(+), 12 deletions(-)
diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h
index 2adae5e0edbfb..bd0ee6a60497b 100644
--- a/libcxx/include/__ranges/to.h
+++ b/libcxx/include/__ranges/to.h
@@ -26,10 +26,10 @@
#include <__ranges/size.h>
#include <__ranges/transform_view.h>
#include <__type_traits/add_pointer.h>
-#include <__type_traits/is_const.h>
-#include <__type_traits/is_volatile.h>
#include <__type_traits/is_class.h>
+#include <__type_traits/is_const.h>
#include <__type_traits/is_union.h>
+#include <__type_traits/is_volatile.h>
#include <__type_traits/type_identity.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
@@ -83,7 +83,7 @@ template <class _Container, input_range _Range, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
- static_assert(is_class_v<_Container>||is_union_v<_Container>, "The target must be a class type");
+ static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type");
// First see if the non-recursive case applies -- the conversion target is either:
// - a range with a convertible value type;
// - a non-range type which might support being created from the input argument(s) (e.g. an `optional`).
@@ -210,7 +210,7 @@ template <class _Container, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
- static_assert(is_class_v<_Container>||is_union_v<_Container>, "The target must be a class type");
+ static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type");
auto __to_func = []<input_range _Range, class... _Tail>(_Range&& __range, _Tail&&... __tail) static
requires requires { //
/**/ ranges::to<_Container>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...);
diff --git a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
index 8e047f9cddf7b..45d967cc07ad4 100644
--- a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
@@ -8,20 +8,72 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-
// Test that the "mandates" requirements on the given class are checked using `static_assert`.
#include <ranges>
-
+void ff() {}
void test() {
+ struct C {
+ int member;
+ int f() { return 0; }
+ };
+
+ enum color { red, green, blue };
+ using member_func_ptr = decltype(&C::f);
+ using member_ptr = decltype(&C::member);
+ using func_ptr = decltype(&ff);
+ using func_t = decltype(ff);
+
struct R {
- int* begin() const { reurn nullptr; };
+ int* begin() const { return nullptr; };
int* end() const { return nullptr; };
operator int() const { return 0; }
+ operator int*() const { return nullptr; }
+ operator func_ptr() const { return nullptr; }
+ operator void() const {}
+ operator member_func_ptr() const { return nullptr; }
+ operator member_ptr() const { return nullptr; }
+ operator color() const { return color::red; }
};
- (void)std::ranges::to<int>(R{});
- //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)(R{} | std::ranges::to<int>());
- //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
-
+ (void)std::ranges::to<int>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<
+ int>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<int*>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<
+ int*>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<func_ptr>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} |
+ std::ranges::to<
+ func_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+
+ (void)std::ranges::to<void>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<
+ void>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<member_ptr>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} |
+ std::ranges::to<
+ member_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<member_func_ptr>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} |
+ std::ranges::to<
+ member_func_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<func_ptr>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} |
+ std::ranges::to<
+ func_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<color>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<
+ color>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)std::ranges::to<func_t>(
+ R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<
+ func_t>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
}
\ No newline at end of file
>From e73c9582c108eccd087f3d8be53ade18b8412360 Mon Sep 17 00:00:00 2001
From: ImoutoCon1999 <ImoutoCon1999 at outlook.com>
Date: Mon, 21 Apr 2025 01:12:56 +0800
Subject: [PATCH 6/6] clarify assert information and correct the test
---
libcxx/include/__ranges/to.h | 4 +--
.../range.utility.conv/to.verify.cpp | 28 +++++++------------
2 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h
index bd0ee6a60497b..3a2bc42969f7b 100644
--- a/libcxx/include/__ranges/to.h
+++ b/libcxx/include/__ranges/to.h
@@ -83,7 +83,7 @@ template <class _Container, input_range _Range, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
- static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type");
+ static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type or union type");
// First see if the non-recursive case applies -- the conversion target is either:
// - a range with a convertible value type;
// - a non-range type which might support being created from the input argument(s) (e.g. an `optional`).
@@ -210,7 +210,7 @@ template <class _Container, class... _Args>
static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const");
static_assert(
!is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile");
- static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type");
+ static_assert(is_class_v<_Container> || is_union_v<_Container>, "The target must be a class type or union type");
auto __to_func = []<input_range _Range, class... _Tail>(_Range&& __range, _Tail&&... __tail) static
requires requires { //
/**/ ranges::to<_Container>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...);
diff --git a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
index 45d967cc07ad4..24185ca600c97 100644
--- a/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.utility/range.utility.conv/to.verify.cpp
@@ -21,7 +21,6 @@ void test() {
using member_func_ptr = decltype(&C::f);
using member_ptr = decltype(&C::member);
using func_ptr = decltype(&ff);
- using func_t = decltype(ff);
struct R {
int* begin() const { return nullptr; };
@@ -30,7 +29,6 @@ void test() {
operator int() const { return 0; }
operator int*() const { return nullptr; }
operator func_ptr() const { return nullptr; }
- operator void() const {}
operator member_func_ptr() const { return nullptr; }
operator member_ptr() const { return nullptr; }
operator color() const { return color::red; }
@@ -49,31 +47,25 @@ void test() {
std::ranges::to<
func_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)std::ranges::to<void>(
- R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)(R{} | std::ranges::to<
- void>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
(void)std::ranges::to<member_ptr>(
R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
(void)(R{} |
std::ranges::to<
member_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)std::ranges::to<member_func_ptr>(
+
+ (void)std::ranges::to<func_t>(
R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)(R{} |
- std::ranges::to<
- member_func_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)std::ranges::to<func_ptr>(
+ (void)(R{} | std::ranges::to<
+ func_t>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+
+ (void)std::ranges::to<void>(
R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)(R{} |
- std::ranges::to<
- func_ptr>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ (void)(R{} | std::ranges::to<
+ void>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
+ //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type.}}
+
(void)std::ranges::to<color>(
R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
(void)(R{} | std::ranges::to<
color>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)std::ranges::to<func_t>(
- R{}); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
- (void)(R{} | std::ranges::to<
- func_t>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target must be a class type}}
}
\ No newline at end of file
More information about the libcxx-commits
mailing list