[libcxx-commits] [libcxx] e06ca31 - [libc++] Canonicalize the ranges results and their tests
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Apr 1 23:26:49 PDT 2022
Author: Nikolas Klauser
Date: 2022-04-02T08:26:31+02:00
New Revision: e06ca312398d9d02da10dc55e6779d1d5d0f9963
URL: https://github.com/llvm/llvm-project/commit/e06ca312398d9d02da10dc55e6779d1d5d0f9963
DIFF: https://github.com/llvm/llvm-project/commit/e06ca312398d9d02da10dc55e6779d1d5d0f9963.diff
LOG: [libc++] Canonicalize the ranges results and their tests
Reviewed By: var-const, Mordante, #libc, ldionne
Spies: ldionne, libcxx-commits
Differential Revision: https://reviews.llvm.org/D121435
Added:
Modified:
libcxx/include/__algorithm/in_fun_result.h
libcxx/include/__algorithm/in_in_out_result.h
libcxx/include/__algorithm/in_in_result.h
libcxx/include/__algorithm/in_out_out_result.h
libcxx/include/__algorithm/in_out_result.h
libcxx/include/__algorithm/min_max_result.h
libcxx/include/__algorithm/ranges_mismatch.h
libcxx/include/__algorithm/ranges_swap_ranges.h
libcxx/test/std/algorithms/algorithms.results/in_found_result.pass.cpp
libcxx/test/std/algorithms/algorithms.results/in_fun_result.pass.cpp
libcxx/test/std/algorithms/algorithms.results/in_in_out_result.pass.cpp
libcxx/test/std/algorithms/algorithms.results/in_in_result.pass.cpp
libcxx/test/std/algorithms/algorithms.results/in_out_out_result.pass.cpp
libcxx/test/std/algorithms/algorithms.results/in_out_result.pass.cpp
libcxx/test/std/algorithms/algorithms.results/min_max_result.pass.cpp
libcxx/test/std/algorithms/algorithms.results/no_unique_address.compile.pass.cpp
libcxx/test/support/test_macros.h
Removed:
libcxx/test/std/algorithms/algorithms.results/in_out_result.compile.pass.cpp
################################################################################
diff --git a/libcxx/include/__algorithm/in_fun_result.h b/libcxx/include/__algorithm/in_fun_result.h
index d502df234aae9..51b5f23460dc9 100644
--- a/libcxx/include/__algorithm/in_fun_result.h
+++ b/libcxx/include/__algorithm/in_fun_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
namespace ranges {
template <class _Ip, class _Fp>
@@ -42,7 +42,7 @@ struct in_fun_result {
};
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/in_in_out_result.h b/libcxx/include/__algorithm/in_in_out_result.h
index 9becf4091dffe..192c9f516c32e 100644
--- a/libcxx/include/__algorithm/in_in_out_result.h
+++ b/libcxx/include/__algorithm/in_in_out_result.h
@@ -41,7 +41,7 @@ struct in_in_out_result {
requires convertible_to<_I1, _II1> && convertible_to<_I2, _II2> && convertible_to<_O1, _OO1>
_LIBCPP_HIDE_FROM_ABI constexpr
operator in_in_out_result<_II1, _II2, _OO1>() && {
- return {_VSTD::move(in1), _VSTD::move(in2), _VSTD::move(out)};
+ return {std::move(in1), std::move(in2), std::move(out)};
}
};
diff --git a/libcxx/include/__algorithm/in_in_result.h b/libcxx/include/__algorithm/in_in_result.h
index 80e69a64747e1..ec36955588b5d 100644
--- a/libcxx/include/__algorithm/in_in_result.h
+++ b/libcxx/include/__algorithm/in_in_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
namespace ranges {
@@ -39,12 +39,14 @@ struct in_in_result {
template <class _II1, class _II2>
requires convertible_to<_I1, _II1> && convertible_to<_I2, _II2>
_LIBCPP_HIDE_FROM_ABI constexpr
- operator in_in_result<_II1, _II2>() && { return {_VSTD::move(in1), _VSTD::move(in2)}; }
+ operator in_in_result<_II1, _II2>() && {
+ return {std::move(in1), std::move(in2)};
+ }
};
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/in_out_out_result.h b/libcxx/include/__algorithm/in_out_out_result.h
index 2125edf2f25a4..b68b4d1d726eb 100644
--- a/libcxx/include/__algorithm/in_out_out_result.h
+++ b/libcxx/include/__algorithm/in_out_out_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
namespace ranges {
template <class _I1, class _O1, class _O2>
@@ -40,12 +40,12 @@ struct in_out_out_result {
requires convertible_to<_I1, _II1> && convertible_to<_O1, _OO1> && convertible_to<_O2, _OO2>
_LIBCPP_HIDE_FROM_ABI constexpr
operator in_out_out_result<_II1, _OO1, _OO2>() && {
- return {_VSTD::move(in), _VSTD::move(out1), _VSTD::move(out2)};
+ return {std::move(in), std::move(out1), std::move(out2)};
}
};
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/in_out_result.h b/libcxx/include/__algorithm/in_out_result.h
index 03e908087102a..8dd8037946de8 100644
--- a/libcxx/include/__algorithm/in_out_result.h
+++ b/libcxx/include/__algorithm/in_out_result.h
@@ -24,24 +24,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
-template<class _InputIterator, class _OutputIterator>
+template<class _I1, class _O1>
struct in_out_result {
- _LIBCPP_NO_UNIQUE_ADDRESS _InputIterator in;
- _LIBCPP_NO_UNIQUE_ADDRESS _OutputIterator out;
+ _LIBCPP_NO_UNIQUE_ADDRESS _I1 in;
+ _LIBCPP_NO_UNIQUE_ADDRESS _O1 out;
- template <class _InputIterator2, class _OutputIterator2>
- requires convertible_to<const _InputIterator&, _InputIterator2> && convertible_to<const _OutputIterator&,
- _OutputIterator2>
+ template <class _I2, class _O2>
+ requires convertible_to<const _I1&, _I2> && convertible_to<const _O1&, _O2>
_LIBCPP_HIDE_FROM_ABI
- constexpr operator in_out_result<_InputIterator2, _OutputIterator2>() const & {
+ constexpr operator in_out_result<_I2, _O2>() const & {
return {in, out};
}
- template <class _InputIterator2, class _OutputIterator2>
- requires convertible_to<_InputIterator, _InputIterator2> && convertible_to<_OutputIterator, _OutputIterator2>
+ template <class _I2, class _O2>
+ requires convertible_to<_I1, _I2> && convertible_to<_O1, _O2>
_LIBCPP_HIDE_FROM_ABI
- constexpr operator in_out_result<_InputIterator2, _OutputIterator2>() && {
- return {_VSTD::move(in), _VSTD::move(out)};
+ constexpr operator in_out_result<_I2, _O2>() && {
+ return {std::move(in), std::move(out)};
}
};
diff --git a/libcxx/include/__algorithm/min_max_result.h b/libcxx/include/__algorithm/min_max_result.h
index 6640866c5bb9d..ca77dcc5725ae 100644
--- a/libcxx/include/__algorithm/min_max_result.h
+++ b/libcxx/include/__algorithm/min_max_result.h
@@ -53,4 +53,4 @@ _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
-#endif
+#endif // _LIBCPP___ALGORITHM_MIN_MAX_RESULT_H
diff --git a/libcxx/include/__algorithm/ranges_mismatch.h b/libcxx/include/__algorithm/ranges_mismatch.h
index 4775daf4f7f69..4c1440b5da061 100644
--- a/libcxx/include/__algorithm/ranges_mismatch.h
+++ b/libcxx/include/__algorithm/ranges_mismatch.h
@@ -27,7 +27,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
namespace ranges {
@@ -78,7 +78,7 @@ inline namespace __cpo {
} // namespace __cpo
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/ranges_swap_ranges.h b/libcxx/include/__algorithm/ranges_swap_ranges.h
index 18067ff3ba1c2..3254e1c60abbd 100644
--- a/libcxx/include/__algorithm/ranges_swap_ranges.h
+++ b/libcxx/include/__algorithm/ranges_swap_ranges.h
@@ -22,7 +22,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -64,6 +64,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
#endif // _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H
diff --git a/libcxx/test/std/algorithms/algorithms.results/in_found_result.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/in_found_result.pass.cpp
index 8b12cf744da78..f0f2a57a6ee36 100644
--- a/libcxx/test/std/algorithms/algorithms.results/in_found_result.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/in_found_result.pass.cpp
@@ -18,21 +18,17 @@
#include "MoveOnly.h"
-template <class T>
-struct ConvertibleFrom {
- constexpr ConvertibleFrom(T c) : content{c} {}
- T content;
-};
-
struct A {
explicit A(int);
};
+// no implicit conversion
static_assert(!std::is_constructible_v<std::ranges::in_found_result<A>, std::ranges::in_found_result<int>>);
struct B {
B(const int&);
B(int&&);
};
+// implicit conversion
static_assert(std::is_constructible_v<std::ranges::in_found_result<B>, std::ranges::in_found_result<int>>);
static_assert(std::is_constructible_v<std::ranges::in_found_result<B>, std::ranges::in_found_result<int>&>);
static_assert(std::is_constructible_v<std::ranges::in_found_result<B>, const std::ranges::in_found_result<int>>);
@@ -43,17 +39,31 @@ struct C {
};
static_assert(!std::is_constructible_v<std::ranges::in_found_result<C>, std::ranges::in_found_result<int>&>);
+// has to be convertible via const&
static_assert(std::is_convertible_v<std::ranges::in_found_result<int>&, std::ranges::in_found_result<long>>);
static_assert(std::is_convertible_v<const std::ranges::in_found_result<int>&, std::ranges::in_found_result<long>>);
static_assert(std::is_convertible_v<std::ranges::in_found_result<int>&&, std::ranges::in_found_result<long>>);
static_assert(std::is_convertible_v<const std::ranges::in_found_result<int>&&, std::ranges::in_found_result<long>>);
+// should be move constructible
+static_assert(std::is_move_constructible_v<std::ranges::in_found_result<MoveOnly>>);
+
+// should not be copy constructible
+static_assert(!std::is_copy_constructible_v<std::ranges::in_found_result<MoveOnly>>);
+
struct NotConvertible {};
+// conversions should not work if there is no conversion
static_assert(!std::is_convertible_v<std::ranges::in_found_result<NotConvertible>, std::ranges::in_found_result<int>>);
static_assert(std::is_same_v<decltype(std::ranges::in_found_result<int>::in), int>);
static_assert(std::is_same_v<decltype(std::ranges::in_found_result<int>::found), bool>);
+template <class T>
+struct ConvertibleFrom {
+ constexpr ConvertibleFrom(T c) : content{c} {}
+ T content;
+};
+
constexpr bool test() {
{
std::ranges::in_found_result<double> res{10, true};
@@ -61,7 +71,7 @@ constexpr bool test() {
assert(res.found == true);
std::ranges::in_found_result<ConvertibleFrom<int>> res2 = res;
assert(res2.in.content == 10);
- assert(res2.found);
+ assert(res2.found == true);
}
{
std::ranges::in_found_result<MoveOnly> res{MoveOnly{}, false};
diff --git a/libcxx/test/std/algorithms/algorithms.results/in_fun_result.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/in_fun_result.pass.cpp
index 3ee843b6c73de..a5a32ec5de90d 100644
--- a/libcxx/test/std/algorithms/algorithms.results/in_fun_result.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/in_fun_result.pass.cpp
@@ -37,9 +37,9 @@ static_assert(std::is_constructible_v<std::ranges::in_fun_result<B, B>, const st
struct C {
C(int&);
};
-// has to be convertible via const&
static_assert(!std::is_constructible_v<std::ranges::in_fun_result<C, C>, std::ranges::in_fun_result<int, int>&>);
+// has to be convertible via const&
static_assert(std::is_convertible_v<std::ranges::in_fun_result<int, int>&, std::ranges::in_fun_result<long, long>>);
static_assert(std::is_convertible_v<const std::ranges::in_fun_result<int, int>&, std::ranges::in_fun_result<long, long>>);
static_assert(std::is_convertible_v<std::ranges::in_fun_result<int, int>&&, std::ranges::in_fun_result<long, long>>);
@@ -55,10 +55,8 @@ static_assert(!std::is_copy_constructible_v<std::ranges::in_fun_result<int, Move
struct NotConvertible {};
// conversions should not work if there is no conversion
-static_assert(!std::is_convertible_v<std::ranges::in_fun_result<NotConvertible, int>,
- std::ranges::in_fun_result<int, int>>);
-static_assert(!std::is_convertible_v<std::ranges::in_fun_result<int, NotConvertible>,
- std::ranges::in_fun_result<int, int>>);
+static_assert(!std::is_convertible_v<std::ranges::in_fun_result<NotConvertible, int>, std::ranges::in_fun_result<int, int>>);
+static_assert(!std::is_convertible_v<std::ranges::in_fun_result<int, NotConvertible>, std::ranges::in_fun_result<int, int>>);
template <class T>
struct ConvertibleFrom {
diff --git a/libcxx/test/std/algorithms/algorithms.results/in_in_out_result.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/in_in_out_result.pass.cpp
index 8c3661a1fdbc7..950cdf3549e2f 100644
--- a/libcxx/test/std/algorithms/algorithms.results/in_in_out_result.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/in_in_out_result.pass.cpp
@@ -18,22 +18,17 @@
#include "MoveOnly.h"
-template <class T>
-struct ConvertibleFrom {
- constexpr ConvertibleFrom(T c) : content{c} {}
- T content;
-};
-
struct A {
explicit A(int);
};
-// conversion is not implicit
+// no implicit conversion
static_assert(!std::is_constructible_v<std::ranges::in_in_out_result<A, A, A>,
std::ranges::in_in_out_result<int, int, int>>);
struct B {
B(int);
};
+// implicit conversion
static_assert(std::is_constructible_v<std::ranges::in_in_out_result<B, B, B>, std::ranges::in_in_out_result<int, int, int>>);
static_assert(std::is_constructible_v<std::ranges::in_in_out_result<B, B, B>, std::ranges::in_in_out_result<int, int, int>&>);
static_assert(std::is_constructible_v<std::ranges::in_in_out_result<B, B, B>, const std::ranges::in_in_out_result<int, int, int>>);
@@ -44,34 +39,34 @@ struct C {
};
static_assert(!std::is_constructible_v<std::ranges::in_in_out_result<C, C, C>, std::ranges::in_in_out_result<int, int, int>&>);
-static_assert(std::is_convertible_v<std::ranges::in_in_out_result<int, int, int>&,
- std::ranges::in_in_out_result<long, long, long>>);
-static_assert(std::is_convertible_v<const std::ranges::in_in_out_result<int, int, int>&,
- std::ranges::in_in_out_result<long, long, long>>);
-static_assert(std::is_convertible_v<std::ranges::in_in_out_result<int, int, int>&&,
- std::ranges::in_in_out_result<long, long, long>>);
-static_assert(std::is_convertible_v<const std::ranges::in_in_out_result<int, int, int>&&,
- std::ranges::in_in_out_result<long, long, long>>);
-
-struct NotConvertible {};
-static_assert(!std::is_convertible_v<std::ranges::in_in_out_result<NotConvertible, int, int>,
- std::ranges::in_in_out_result<int, int, int>>);
-static_assert(!std::is_convertible_v<std::ranges::in_in_out_result<int, NotConvertible, int>,
- std::ranges::in_in_out_result<int, int, int>>);
-static_assert(!std::is_convertible_v<std::ranges::in_in_out_result<int, int, NotConvertible>,
- std::ranges::in_in_out_result<int, int, int>>);
-
-static_assert(std::is_constructible_v<std::ranges::in_in_out_result<MoveOnly, MoveOnly, MoveOnly>,
- std::ranges::in_in_out_result<int, int, int>&>);
+// has to be convertible via const&
+static_assert(std::is_convertible_v<std::ranges::in_in_out_result<int, int, int>&, std::ranges::in_in_out_result<long, long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_in_out_result<int, int, int>&, std::ranges::in_in_out_result<long, long, long>>);
+static_assert(std::is_convertible_v<std::ranges::in_in_out_result<int, int, int>&&, std::ranges::in_in_out_result<long, long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_in_out_result<int, int, int>&&, std::ranges::in_in_out_result<long, long, long>>);
+// should be move constructible
static_assert(std::is_move_constructible_v<std::ranges::in_in_out_result<MoveOnly, int, int>>);
static_assert(std::is_move_constructible_v<std::ranges::in_in_out_result<int, MoveOnly, int>>);
static_assert(std::is_move_constructible_v<std::ranges::in_in_out_result<int, int, MoveOnly>>);
+// should not be copy constructible
static_assert(!std::is_copy_constructible_v<std::ranges::in_in_out_result<MoveOnly, int, int>>);
static_assert(!std::is_copy_constructible_v<std::ranges::in_in_out_result<int, MoveOnly, int>>);
static_assert(!std::is_copy_constructible_v<std::ranges::in_in_out_result<int, int, MoveOnly>>);
+struct NotConvertible {};
+// conversions should not work if there is no conversion
+static_assert(!std::is_convertible_v<std::ranges::in_in_out_result<NotConvertible, int, int>, std::ranges::in_in_out_result<int, int, int>>);
+static_assert(!std::is_convertible_v<std::ranges::in_in_out_result<int, NotConvertible, int>, std::ranges::in_in_out_result<int, int, int>>);
+static_assert(!std::is_convertible_v<std::ranges::in_in_out_result<int, int, NotConvertible>, std::ranges::in_in_out_result<int, int, int>>);
+
+template <class T>
+struct ConvertibleFrom {
+ constexpr ConvertibleFrom(T c) : content{c} {}
+ T content;
+};
+
constexpr bool test() {
{
std::ranges::in_in_out_result<int, double, float> res{10, 0., 1.f};
diff --git a/libcxx/test/std/algorithms/algorithms.results/in_in_result.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/in_in_result.pass.cpp
index bf1b0ad3f2f55..52369a07d253a 100644
--- a/libcxx/test/std/algorithms/algorithms.results/in_in_result.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/in_in_result.pass.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// template <class I1, class I2>
// struct in_in_result;
@@ -17,22 +18,16 @@
#include "MoveOnly.h"
-template <class T>
-struct ConstructibleFrom {
- constexpr ConstructibleFrom(T c) : content{c} {}
- T content;
-};
-
struct A {
explicit A(int);
};
-static_assert(!std::is_constructible_v<std::ranges::in_in_result<A, A>,
- std::ranges::in_in_result<int, int>>);
+// no implicit conversion
+static_assert(!std::is_constructible_v<std::ranges::in_in_result<A, A>, std::ranges::in_in_result<int, int>>);
struct B {
- B(const int&);
- B(int&&);
+ B(int);
};
+// implicit conversion
static_assert(std::is_constructible_v<std::ranges::in_in_result<B, B>, std::ranges::in_in_result<int, int>>);
static_assert(std::is_constructible_v<std::ranges::in_in_result<B, B>, std::ranges::in_in_result<int, int>&>);
static_assert(std::is_constructible_v<std::ranges::in_in_result<B, B>, const std::ranges::in_in_result<int, int>>);
@@ -43,20 +38,26 @@ struct C {
};
static_assert(!std::is_constructible_v<std::ranges::in_in_result<C, C>, std::ranges::in_in_result<int, int>&>);
-static_assert(std::is_convertible_v< std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
-static_assert(std::is_convertible_v< const std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
-static_assert(std::is_convertible_v< std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
-static_assert(std::is_convertible_v< const std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
+// has to be convertible via const&
+static_assert(std::is_convertible_v<std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_in_result<int, int>&, std::ranges::in_in_result<long, long>>);
+static_assert(std::is_convertible_v<std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_in_result<int, int>&&, std::ranges::in_in_result<long, long>>);
+
+// should be move constructible
+static_assert(std::is_move_constructible_v<std::ranges::in_in_result<MoveOnly, int>>);
+static_assert(std::is_move_constructible_v<std::ranges::in_in_result<int, MoveOnly>>);
struct NotConvertible {};
-static_assert(!std::is_convertible_v<std::ranges::in_in_result<NotConvertible, int>,
- std::ranges::in_in_result<int, int>>);
-static_assert(!std::is_convertible_v<std::ranges::in_in_result<int, NotConvertible>,
- std::ranges::in_in_result<int, int>>);
+// conversions should not work if there is no conversion
+static_assert(!std::is_convertible_v<std::ranges::in_in_result<NotConvertible, int>, std::ranges::in_in_result<int, int>>);
+static_assert(!std::is_convertible_v<std::ranges::in_in_result<int, NotConvertible>, std::ranges::in_in_result<int, int>>);
+
+template <class T>
+struct ConstructibleFrom {
+ constexpr ConstructibleFrom(T c) : content{c} {}
+ T content;
+};
constexpr bool test() {
{
@@ -73,9 +74,11 @@ constexpr bool test() {
[[maybe_unused]] auto res2 = static_cast<std::ranges::in_in_result<MoveOnly, int>>(std::move(res));
assert(res.in1.get() == 0);
}
- auto [in1, in2] = std::ranges::in_in_result<int, int>{1, 2};
- assert(in1 == 1);
- assert(in2 == 2);
+ {
+ auto [in1, in2] = std::ranges::in_in_result<int, int>{1, 2};
+ assert(in1 == 1);
+ assert(in2 == 2);
+ }
return true;
}
diff --git a/libcxx/test/std/algorithms/algorithms.results/in_out_out_result.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/in_out_out_result.pass.cpp
index 1168f233baa0b..968254883d479 100644
--- a/libcxx/test/std/algorithms/algorithms.results/in_out_out_result.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/in_out_out_result.pass.cpp
@@ -18,22 +18,16 @@
#include "MoveOnly.h"
-template <class T>
-struct ConvertibleFrom {
- constexpr ConvertibleFrom(T c) : content{c} {}
- T content;
-};
-
struct A {
explicit A(int);
};
-// conversion is not implicit
-static_assert(!std::is_constructible_v<std::ranges::in_out_out_result<A, A, A>,
- std::ranges::in_out_out_result<int, int, int>>);
+// no implicit conversion
+static_assert(!std::is_constructible_v<std::ranges::in_out_out_result<A, A, A>, std::ranges::in_out_out_result<int, int, int>>);
struct B {
B(int);
};
+// implicit conversion
static_assert(std::is_constructible_v<std::ranges::in_out_out_result<B, B, B>, std::ranges::in_out_out_result<int, int, int>>);
static_assert(std::is_constructible_v<std::ranges::in_out_out_result<B, B, B>, std::ranges::in_out_out_result<int, int, int>&>);
static_assert(std::is_constructible_v<std::ranges::in_out_out_result<B, B, B>, const std::ranges::in_out_out_result<int, int, int>>);
@@ -44,26 +38,13 @@ struct C {
};
static_assert(!std::is_constructible_v<std::ranges::in_out_out_result<C, C, C>, std::ranges::in_out_out_result<int, int, int>&>);
-static_assert(std::is_convertible_v<std::ranges::in_out_out_result<int, int, int>&,
- std::ranges::in_out_out_result<long, long, long>>);
-static_assert(std::is_convertible_v<const std::ranges::in_out_out_result<int, int, int>&,
- std::ranges::in_out_out_result<long, long, long>>);
-static_assert(std::is_convertible_v<std::ranges::in_out_out_result<int, int, int>&&,
- std::ranges::in_out_out_result<long, long, long>>);
-static_assert(std::is_convertible_v<const std::ranges::in_out_out_result<int, int, int>&&,
- std::ranges::in_out_out_result<long, long, long>>);
-
-struct NotConvertible {};
-static_assert(!std::is_convertible_v<std::ranges::in_out_out_result<NotConvertible, int, int>,
- std::ranges::in_out_out_result<int, int, int>>);
-static_assert(!std::is_convertible_v<std::ranges::in_out_out_result<int, NotConvertible, int>,
- std::ranges::in_out_out_result<int, int, int>>);
-static_assert(!std::is_convertible_v<std::ranges::in_out_out_result<int, int, NotConvertible>,
- std::ranges::in_out_out_result<int, int, int>>);
-
-static_assert(std::is_constructible_v<std::ranges::in_out_out_result<MoveOnly, MoveOnly, MoveOnly>,
- std::ranges::in_out_out_result<int, int, int>&>);
+// has to be convertible via const&
+static_assert(std::is_convertible_v<std::ranges::in_out_out_result<int, int, int>&, std::ranges::in_out_out_result<long, long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_out_out_result<int, int, int>&, std::ranges::in_out_out_result<long, long, long>>);
+static_assert(std::is_convertible_v<std::ranges::in_out_out_result<int, int, int>&&, std::ranges::in_out_out_result<long, long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_out_out_result<int, int, int>&&, std::ranges::in_out_out_result<long, long, long>>);
+// should be move constructible
static_assert(std::is_move_constructible_v<std::ranges::in_out_out_result<MoveOnly, int, int>>);
static_assert(std::is_move_constructible_v<std::ranges::in_out_out_result<int, MoveOnly, int>>);
static_assert(std::is_move_constructible_v<std::ranges::in_out_out_result<int, int, MoveOnly>>);
@@ -72,6 +53,18 @@ static_assert(!std::is_copy_constructible_v<std::ranges::in_out_out_result<MoveO
static_assert(!std::is_copy_constructible_v<std::ranges::in_out_out_result<int, MoveOnly, int>>);
static_assert(!std::is_copy_constructible_v<std::ranges::in_out_out_result<int, int, MoveOnly>>);
+struct NotConvertible {};
+// conversions should not work if there is no conversion
+static_assert(!std::is_convertible_v<std::ranges::in_out_out_result<NotConvertible, int, int>, std::ranges::in_out_out_result<int, int, int>>);
+static_assert(!std::is_convertible_v<std::ranges::in_out_out_result<int, NotConvertible, int>, std::ranges::in_out_out_result<int, int, int>>);
+static_assert(!std::is_convertible_v<std::ranges::in_out_out_result<int, int, NotConvertible>, std::ranges::in_out_out_result<int, int, int>>);
+
+template <class T>
+struct ConvertibleFrom {
+ constexpr ConvertibleFrom(T c) : content{c} {}
+ T content;
+};
+
constexpr bool test() {
{
std::ranges::in_out_out_result<int, double, float> res{10, 0., 1.f};
diff --git a/libcxx/test/std/algorithms/algorithms.results/in_out_result.compile.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/in_out_result.compile.pass.cpp
deleted file mode 100644
index 317e759dcf492..0000000000000
--- a/libcxx/test/std/algorithms/algorithms.results/in_out_result.compile.pass.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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-has-no-incomplete-ranges
-//
-// clang-cl and cl currently don't support [[no_unique_address]]
-// XFAIL: msvc
-
-// namespace ranges {
-// template<class InputIterator, class OutputIterator>
-// struct in_out_result;
-// }
-
-#include <algorithm>
-
-// Size optimization.
-struct Empty {};
-struct Empty2 {};
-
-static_assert(sizeof(std::ranges::in_out_result<Empty, int>) == sizeof(int));
-static_assert(sizeof(std::ranges::in_out_result<int, Empty>) == sizeof(int));
-static_assert(sizeof(std::ranges::in_out_result<Empty, Empty2>) == sizeof(char));
diff --git a/libcxx/test/std/algorithms/algorithms.results/in_out_result.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/in_out_result.pass.cpp
index eb04591d6491c..fed18086e1721 100644
--- a/libcxx/test/std/algorithms/algorithms.results/in_out_result.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/in_out_result.pass.cpp
@@ -9,125 +9,85 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
-// <algorithm>
-//
-// namespace ranges {
-// template<class InputIterator, class OutputIterator>
-// struct in_out_result;
-// }
+// template <class I1, class O1>
+// struct in_out_result;
#include <algorithm>
#include <cassert>
#include <type_traits>
+#include "MoveOnly.h"
+
struct A {
- A(int&);
+ explicit A(int);
};
-static_assert(!std::is_constructible_v<std::ranges::in_out_result<A, A>, std::ranges::in_out_result<int, int>&>);
+// no implicit conversion
+static_assert(!std::is_constructible_v<std::ranges::in_out_result<A, A>, std::ranges::in_out_result<int, int>>);
-static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&,
- std::ranges::in_out_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<std::ranges::in_out_result<int, int>&,
- std::ranges::in_out_result<long, long>>);
-static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&,
- std::ranges::in_out_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_out_result<int, int>&,
- std::ranges::in_out_result<long, long>>);
-static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&&,
- std::ranges::in_out_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<std::ranges::in_out_result<int, int>&&,
- std::ranges::in_out_result<long, long>>);
-static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&&,
- std::ranges::in_out_result<long, long>>);
-static_assert(!std::is_nothrow_convertible_v<const std::ranges::in_out_result<int, int>&&,
- std::ranges::in_out_result<long, long>>);
+struct B {
+ B(int);
+};
+// implicit conversion
+static_assert(std::is_constructible_v<std::ranges::in_out_result<B, B>, std::ranges::in_out_result<int, int>>);
+static_assert(std::is_constructible_v<std::ranges::in_out_result<B, B>, std::ranges::in_out_result<int, int>&>);
+static_assert(std::is_constructible_v<std::ranges::in_out_result<B, B>, const std::ranges::in_out_result<int, int>>);
+static_assert(std::is_constructible_v<std::ranges::in_out_result<B, B>, const std::ranges::in_out_result<int, int>&>);
+
+struct C {
+ C(int&);
+};
+static_assert(!std::is_constructible_v<std::ranges::in_out_result<C, C>, std::ranges::in_out_result<int, int>&>);
+
+// has to be convertible via const&
+static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&, std::ranges::in_out_result<long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&, std::ranges::in_out_result<long, long>>);
+static_assert(std::is_convertible_v<std::ranges::in_out_result<int, int>&&, std::ranges::in_out_result<long, long>>);
+static_assert(std::is_convertible_v<const std::ranges::in_out_result<int, int>&&, std::ranges::in_out_result<long, long>>);
+
+// should be move constructible
+static_assert(std::is_move_constructible_v<std::ranges::in_out_result<MoveOnly, int>>);
+static_assert(std::is_move_constructible_v<std::ranges::in_out_result<int, MoveOnly>>);
+
+struct NotConvertible {};
+// conversions should not work if there is no conversion
+static_assert(!std::is_convertible_v<std::ranges::in_out_result<NotConvertible, int>, std::ranges::in_out_result<int, NotConvertible>>);
+static_assert(!std::is_convertible_v<std::ranges::in_out_result<int, NotConvertible>, std::ranges::in_out_result<NotConvertible, int>>);
+
+template <class T>
+struct ConvertibleFrom {
+ constexpr ConvertibleFrom(T c) : content{c} {}
+ T content;
+};
-int main(int, char**) {
- // Conversion, fundamental types.
+constexpr bool test() {
{
- std::ranges::in_out_result<int, bool> x = {2, false};
- // FIXME(varconst): try a narrowing conversion.
- std::ranges::in_out_result<long, char> y = x;
- assert(y.in == 2);
- assert(y.out == '\0');
+ std::ranges::in_out_result<double, int> res{10, 1};
+ assert(res.in == 10);
+ assert(res.out == 1);
+ std::ranges::in_out_result<ConvertibleFrom<double>, ConvertibleFrom<int>> res2 = res;
+ assert(res2.in.content == 10);
+ assert(res2.out.content == 1);
}
-
- // Conversion, user-defined types.
{
- struct From1 {
- int value = 0;
- From1(int v) : value(v) {}
- };
-
- struct To1 {
- int value = 0;
- To1(int v) : value(v) {}
-
- To1(const From1& f) : value(f.value) {};
- };
-
- struct To2 {
- int value = 0;
- To2(int v) : value(v) {}
- };
- struct From2 {
- int value = 0;
- From2(int v) : value(v) {}
-
- operator To2() const { return To2(value); }
- };
-
- std::ranges::in_out_result<From1, From2> x{42, 99};
- std::ranges::in_out_result<To1, To2> y = x;
- assert(y.in.value == 42);
- assert(y.out.value == 99);
+ std::ranges::in_out_result<MoveOnly, int> res{MoveOnly{}, 10};
+ assert(res.in.get() == 1);
+ assert(res.out == 10);
+ auto res2 = std::move(res);
+ assert(res.in.get() == 0);
+ assert(res.out == 10);
+ assert(res2.in.get() == 1);
+ assert(res2.out == 10);
}
-
- // Copy-only type.
{
- struct CopyOnly {
- int value = 0;
- CopyOnly() = default;
- CopyOnly(int v) : value(v) {}
-
- CopyOnly(const CopyOnly&) = default;
- CopyOnly(CopyOnly&&) = delete;
- };
-
- std::ranges::in_out_result<CopyOnly, CopyOnly> x;
- x.in.value = 42;
- x.out.value = 99;
-
- auto y = x;
- assert(y.in.value == 42);
- assert(y.out.value == 99);
- }
-
- // Move-only type.
- {
- struct MoveOnly {
- int value = 0;
- MoveOnly(int v) : value(v) {}
-
- MoveOnly(MoveOnly&&) = default;
- MoveOnly(const MoveOnly&) = delete;
- };
-
- std::ranges::in_out_result<MoveOnly, MoveOnly> x{42, 99};
- auto y = std::move(x);
- assert(y.in.value == 42);
- assert(y.out.value == 99);
+ auto [min, max] = std::ranges::in_out_result<int, int>{1, 2};
+ assert(min == 1);
+ assert(max == 2);
}
- // Unsuccessful conversion.
- {
- struct Foo1 {};
- struct Foo2 {};
- struct Bar1 {};
- struct Bar2 {};
- static_assert(
- !std::is_convertible_v<std::ranges::in_out_result<Foo1, Foo2>, std::ranges::in_out_result<Bar1, Bar2>>);
- }
+ return true;
+}
- return 0;
+int main(int, char**) {
+ test();
+ static_assert(test());
}
diff --git a/libcxx/test/std/algorithms/algorithms.results/min_max_result.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/min_max_result.pass.cpp
index 56cc32b0feff9..3f89199a0ac16 100644
--- a/libcxx/test/std/algorithms/algorithms.results/min_max_result.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/min_max_result.pass.cpp
@@ -18,21 +18,16 @@
#include "MoveOnly.h"
-template <class T>
-struct ConvertibleFrom {
- constexpr ConvertibleFrom(T c) : content{c} {}
- T content;
-};
-
struct A {
explicit A(int);
};
+// no implicit conversion
static_assert(!std::is_constructible_v<std::ranges::min_max_result<A>, std::ranges::min_max_result<int>>);
struct B {
- B(const int&);
- B(int&&);
+ B(int);
};
+// implicit conversion
static_assert(std::is_constructible_v<std::ranges::min_max_result<B>, std::ranges::min_max_result<int>>);
static_assert(std::is_constructible_v<std::ranges::min_max_result<B>, std::ranges::min_max_result<int>&>);
static_assert(std::is_constructible_v<std::ranges::min_max_result<B>, const std::ranges::min_max_result<int>>);
@@ -43,14 +38,28 @@ struct C {
};
static_assert(!std::is_constructible_v<std::ranges::min_max_result<C>, std::ranges::min_max_result<int>&>);
+// has to be convertible via const&
static_assert(std::is_convertible_v<std::ranges::min_max_result<int>&, std::ranges::min_max_result<long>>);
static_assert(std::is_convertible_v<const std::ranges::min_max_result<int>&, std::ranges::min_max_result<long>>);
static_assert(std::is_convertible_v<std::ranges::min_max_result<int>&&, std::ranges::min_max_result<long>>);
static_assert(std::is_convertible_v<const std::ranges::min_max_result<int>&&, std::ranges::min_max_result<long>>);
+// should be move constructible
+static_assert(std::is_move_constructible_v<std::ranges::min_max_result<MoveOnly>>);
+
+// should not be copy constructible
+static_assert(!std::is_copy_constructible_v<std::ranges::min_max_result<MoveOnly>>);
+
struct NotConvertible {};
+// conversions should not work if there is no conversion
static_assert(!std::is_convertible_v<std::ranges::min_max_result<NotConvertible>, std::ranges::min_max_result<int>>);
+template <class T>
+struct ConvertibleFrom {
+ constexpr ConvertibleFrom(T c) : content{c} {}
+ T content;
+};
+
constexpr bool test() {
{
std::ranges::min_max_result<double> res{10, 1};
@@ -64,13 +73,17 @@ constexpr bool test() {
std::ranges::min_max_result<MoveOnly> res{MoveOnly{}, MoveOnly{}};
assert(res.min.get() == 1);
assert(res.max.get() == 1);
- [[maybe_unused]] auto res2 = static_cast<std::ranges::min_max_result<MoveOnly>>(std::move(res));
+ auto res2 = std::move(res);
assert(res.min.get() == 0);
assert(res.max.get() == 0);
+ assert(res2.min.get() == 1);
+ assert(res2.max.get() == 1);
+ }
+ {
+ auto [min, max] = std::ranges::min_max_result<int>{1, 2};
+ assert(min == 1);
+ assert(max == 2);
}
- auto [min, max] = std::ranges::min_max_result<int>{1, 2};
- assert(min == 1);
- assert(max == 2);
return true;
}
diff --git a/libcxx/test/std/algorithms/algorithms.results/no_unique_address.compile.pass.cpp b/libcxx/test/std/algorithms/algorithms.results/no_unique_address.compile.pass.cpp
index fe62869478511..fadb64bad976b 100644
--- a/libcxx/test/std/algorithms/algorithms.results/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/std/algorithms/algorithms.results/no_unique_address.compile.pass.cpp
@@ -19,13 +19,23 @@
#include <algorithm>
+#include "test_macros.h"
+
struct Empty {};
struct Empty2 {};
+static_assert(sizeof(std::ranges::in_fun_result<Empty, int>) == sizeof(int));
+static_assert(sizeof(std::ranges::in_fun_result<int, Empty>) == sizeof(int));
+static_assert(sizeof(std::ranges::in_fun_result<Empty, Empty>) == 2);
+
static_assert(sizeof(std::ranges::in_in_result<Empty, int>) == sizeof(int));
static_assert(sizeof(std::ranges::in_in_result<int, Empty>) == sizeof(int));
static_assert(sizeof(std::ranges::in_in_result<Empty, Empty>) == 2);
+static_assert(sizeof(std::ranges::in_out_result<Empty, int>) == sizeof(int));
+static_assert(sizeof(std::ranges::in_out_result<int, Empty>) == sizeof(int));
+static_assert(sizeof(std::ranges::in_out_result<Empty, Empty2>) == sizeof(char));
+
static_assert(sizeof(std::ranges::in_in_out_result<Empty, int, int>) == 2 * sizeof(int));
static_assert(sizeof(std::ranges::in_in_out_result<int, Empty, int>) == 2 * sizeof(int));
static_assert(sizeof(std::ranges::in_in_out_result<int, int, Empty>) == 2 * sizeof(int));
@@ -44,6 +54,15 @@ static_assert(sizeof(std::ranges::in_out_out_result<Empty, Empty, char>) == 2);
static_assert(sizeof(std::ranges::in_out_out_result<int, Empty, Empty2>) == sizeof(int));
static_assert(sizeof(std::ranges::in_out_out_result<Empty, Empty, Empty>) == 3);
-static_assert(sizeof(std::ranges::in_fun_result<Empty, int>) == sizeof(int));
-static_assert(sizeof(std::ranges::in_fun_result<int, Empty>) == sizeof(int));
-static_assert(sizeof(std::ranges::in_fun_result<Empty, Empty>) == 2);
+// In min_max_result both elements have the same type, so they can't have the same address.
+// So the only way to test that [[no_unique_address]] is used is to have it in another struct
+struct MinMaxNoUniqueAddress {
+ int a;
+ TEST_NO_UNIQUE_ADDRESS std::ranges::min_max_result<Empty> b;
+ int c;
+};
+
+static_assert(sizeof(std::ranges::min_max_result<Empty>) == 2);
+static_assert(sizeof(MinMaxNoUniqueAddress) == 8);
+
+static_assert(sizeof(std::ranges::in_found_result<Empty>) == sizeof(bool));
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index aa6159496018f..60dd8e7e3b48f 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -415,4 +415,12 @@ inline void DoNotOptimize(Tp const& value) {
# define TEST_MSVC_DIAGNOSTIC_IGNORED(num)
#endif
+#if __has_cpp_attribute(msvc::no_unique_address)
+#define TEST_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
+#elif __has_cpp_attribute(no_unique_address)
+#define TEST_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#else
+#define TEST_NO_UNIQUE_ADDRESS
+#endif
+
#endif // SUPPORT_TEST_MACROS_HPP
More information about the libcxx-commits
mailing list