[libc++][ranges] Reject non-class types in ranges::to (#135802)
This patch adds `static_assert` using `is_class_v` and `is_union_v` to reject no-class type template parameters. Fixes #132133 --------- Co-authored-by: A. Jiang <de34@live.cn>
This commit is contained in:
@@ -26,7 +26,9 @@
|
||||
#include <__ranges/size.h>
|
||||
#include <__ranges/transform_view.h>
|
||||
#include <__type_traits/add_pointer.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>
|
||||
@@ -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 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`).
|
||||
@@ -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 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)...);
|
||||
|
||||
@@ -14,12 +14,79 @@
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
|
||||
void test() {
|
||||
void test_cv_qualifications() {
|
||||
using R = std::vector<int>;
|
||||
R in = {1, 2, 3};
|
||||
R in = {1, 2, 3};
|
||||
|
||||
(void)std::ranges::to<const R>(in); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
|
||||
(void)(in | std::ranges::to<const R>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
|
||||
(void)std::ranges::to<volatile R>(in); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
|
||||
(void)(in | std::ranges::to<volatile R>()); //expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
|
||||
//expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
|
||||
(void)std::ranges::to<const R>(in);
|
||||
//expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be const-qualified, please remove the const}}
|
||||
(void)(in | std::ranges::to<const R>());
|
||||
|
||||
//expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
|
||||
(void)std::ranges::to<volatile R>(in);
|
||||
|
||||
//expected-error-re@*:* {{static assertion failed{{.*}}The target container cannot be volatile-qualified, please remove the volatile}}
|
||||
(void)(in | std::ranges::to<volatile R>());
|
||||
}
|
||||
//unexpected_types
|
||||
void ff();
|
||||
void test_unexpected_types() {
|
||||
struct C {
|
||||
int member;
|
||||
int f();
|
||||
};
|
||||
|
||||
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 { return nullptr; };
|
||||
int* end() const { return nullptr; };
|
||||
|
||||
operator int() const;
|
||||
operator int*() const;
|
||||
operator func_ptr() const;
|
||||
operator member_func_ptr() const;
|
||||
operator member_ptr() const;
|
||||
operator color() const;
|
||||
};
|
||||
//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<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<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}}
|
||||
(void)std::ranges::to<void>(R{});
|
||||
//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)(R{} | std::ranges::to<void>());
|
||||
|
||||
//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>());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user