forked from OSchip/llvm-project
[libc++] [C++20] [P0586] Implement safe integral comparisons
* https://wg21.link/P0586 Reviewed By: #libc, curdeius, Quuxplusone Differential Revision: https://reviews.llvm.org/D94511
This commit is contained in:
parent
cf899a31ae
commit
36c3918ec5
|
@ -164,7 +164,7 @@
|
|||
"`P1961 <https://wg21.link/P1961>`__","LWG","Harmonizing the definitions of total order for pointers","Belfast","* *",""
|
||||
"`P1965 <https://wg21.link/P1965>`__","LWG","Blanket Wording for Specifying ""Hidden Friends""","Belfast","* *",""
|
||||
"","","","","",""
|
||||
"`P0586 <https://wg21.link/P0586>`__","LWG","Safe integral comparisons","Prague","* *",""
|
||||
"`P0586 <https://wg21.link/P0586>`__","LWG","Safe integral comparisons","Prague","|Complete|","13.0"
|
||||
"`P0593 <https://wg21.link/P0593>`__","CWG","Implicit creation of objects for low-level object manipulation","Prague","* *",""
|
||||
"`P1115 <https://wg21.link/P1115>`__","LWG","Improving the Return Value of Erase-Like Algorithms II: Free erase/erase if","Prague","|Complete|","11.0"
|
||||
"`P1243 <https://wg21.link/P1243>`__","LWG","Rangify New Algorithms","Prague","* *",""
|
||||
|
|
|
|
@ -240,7 +240,7 @@ Status
|
|||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_int_pow2`` ``202002L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_integer_comparison_functions`` *unimplemented*
|
||||
``__cpp_lib_integer_comparison_functions`` ``202002L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_interpolate`` ``201902L``
|
||||
------------------------------------------------- -----------------
|
||||
|
|
|
@ -58,6 +58,14 @@ template <class T> void as_const(const T&&) = delete; // C+
|
|||
|
||||
template <class T> typename add_rvalue_reference<T>::type declval() noexcept;
|
||||
|
||||
template<class T, class U> constexpr bool cmp_equal(T t, U u) noexcept; // C++20
|
||||
template<class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept; // C++20
|
||||
template<class T, class U> constexpr bool cmp_less(T t, U u) noexcept; // C++20
|
||||
template<class T, class U> constexpr bool cmp_greater(T t, U u) noexcept; // C++20
|
||||
template<class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept; // C++20
|
||||
template<class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept; // C++20
|
||||
template<class R, class T> constexpr bool in_range(T t) noexcept; // C++20
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair
|
||||
{
|
||||
|
@ -207,6 +215,7 @@ template <class T>
|
|||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <version>
|
||||
#include <__debug>
|
||||
|
||||
|
@ -214,6 +223,9 @@ template <class T>
|
|||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace rel_ops
|
||||
|
@ -284,6 +296,82 @@ template <class _Tp>
|
|||
void as_const(const _Tp&&) = delete;
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
template<class _Tp, class... _Up>
|
||||
struct _IsSameAsAny : _Or<_IsSame<_Tp, _Up>...> {};
|
||||
|
||||
template<class _Tp>
|
||||
concept __is_safe_integral_cmp = is_integral_v<_Tp> &&
|
||||
!_IsSameAsAny<_Tp, bool, char,
|
||||
#ifndef _LIBCPP_NO_HAS_CHAR8_T
|
||||
char8_t,
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
char16_t, char32_t,
|
||||
#endif
|
||||
wchar_t>::value;
|
||||
|
||||
template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
bool cmp_equal(_Tp __t, _Up __u) noexcept
|
||||
{
|
||||
if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
|
||||
return __t == __u;
|
||||
else if constexpr (is_signed_v<_Tp>)
|
||||
return __t < 0 ? false : make_unsigned_t<_Tp>(__t) == __u;
|
||||
else
|
||||
return __u < 0 ? false : __t == make_unsigned_t<_Up>(__u);
|
||||
}
|
||||
|
||||
template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
bool cmp_not_equal(_Tp __t, _Up __u) noexcept
|
||||
{
|
||||
return !_VSTD::cmp_equal(__t, __u);
|
||||
}
|
||||
|
||||
template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
bool cmp_less(_Tp __t, _Up __u) noexcept
|
||||
{
|
||||
if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
|
||||
return __t < __u;
|
||||
else if constexpr (is_signed_v<_Tp>)
|
||||
return __t < 0 ? true : make_unsigned_t<_Tp>(__t) < __u;
|
||||
else
|
||||
return __u < 0 ? false : __t < make_unsigned_t<_Up>(__u);
|
||||
}
|
||||
|
||||
template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
bool cmp_greater(_Tp __t, _Up __u) noexcept
|
||||
{
|
||||
return _VSTD::cmp_less(__u, __t);
|
||||
}
|
||||
|
||||
template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
bool cmp_less_equal(_Tp __t, _Up __u) noexcept
|
||||
{
|
||||
return !_VSTD::cmp_greater(__t, __u);
|
||||
}
|
||||
|
||||
template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
bool cmp_greater_equal(_Tp __t, _Up __u) noexcept
|
||||
{
|
||||
return !_VSTD::cmp_less(__t, __u);
|
||||
}
|
||||
|
||||
template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
bool in_range(_Up __u) noexcept
|
||||
{
|
||||
return _VSTD::cmp_less_equal(__u, numeric_limits<_Tp>::max()) &&
|
||||
_VSTD::cmp_greater_equal(__u, numeric_limits<_Tp>::min());
|
||||
}
|
||||
#endif
|
||||
|
||||
struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { explicit piecewise_construct_t() = default; };
|
||||
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;// = piecewise_construct_t();
|
||||
|
@ -1647,4 +1735,6 @@ to_underlying(_Tp __val) noexcept {
|
|||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_UTILITY
|
||||
|
|
|
@ -322,7 +322,9 @@ __cpp_lib_void_t 201411L <type_traits>
|
|||
// # define __cpp_lib_format 201907L
|
||||
# define __cpp_lib_generic_unordered_lookup 201811L
|
||||
# define __cpp_lib_int_pow2 202002L
|
||||
// # define __cpp_lib_integer_comparison_functions 202002L
|
||||
# if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
# define __cpp_lib_integer_comparison_functions 202002L
|
||||
# endif
|
||||
# define __cpp_lib_interpolate 201902L
|
||||
# if !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
|
||||
# define __cpp_lib_is_constant_evaluated 201811L
|
||||
|
|
|
@ -184,16 +184,16 @@
|
|||
# error "__cpp_lib_exchange_function should have the value 201304L in c++20"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# if defined(__cpp_concepts) && __cpp_concepts >= 201907L
|
||||
# ifndef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should be defined in c++20"
|
||||
# endif
|
||||
# if __cpp_lib_integer_comparison_functions != 202002L
|
||||
# error "__cpp_lib_integer_comparison_functions should have the value 202002L in c++20"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# else
|
||||
# ifdef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined because it is unimplemented in libc++!"
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined when defined(__cpp_concepts) && __cpp_concepts >= 201907L is not defined!"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
@ -251,16 +251,16 @@
|
|||
# error "__cpp_lib_exchange_function should have the value 201304L in c++2b"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# if defined(__cpp_concepts) && __cpp_concepts >= 201907L
|
||||
# ifndef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should be defined in c++2b"
|
||||
# endif
|
||||
# if __cpp_lib_integer_comparison_functions != 202002L
|
||||
# error "__cpp_lib_integer_comparison_functions should have the value 202002L in c++2b"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# else
|
||||
# ifdef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined because it is unimplemented in libc++!"
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined when defined(__cpp_concepts) && __cpp_concepts >= 201907L is not defined!"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
|
|
@ -2653,16 +2653,16 @@
|
|||
# error "__cpp_lib_int_pow2 should have the value 202002L in c++20"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# if defined(__cpp_concepts) && __cpp_concepts >= 201907L
|
||||
# ifndef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should be defined in c++20"
|
||||
# endif
|
||||
# if __cpp_lib_integer_comparison_functions != 202002L
|
||||
# error "__cpp_lib_integer_comparison_functions should have the value 202002L in c++20"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# else
|
||||
# ifdef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined because it is unimplemented in libc++!"
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined when defined(__cpp_concepts) && __cpp_concepts >= 201907L is not defined!"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
@ -3834,16 +3834,16 @@
|
|||
# error "__cpp_lib_int_pow2 should have the value 202002L in c++2b"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# if defined(__cpp_concepts) && __cpp_concepts >= 201907L
|
||||
# ifndef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should be defined in c++2b"
|
||||
# endif
|
||||
# if __cpp_lib_integer_comparison_functions != 202002L
|
||||
# error "__cpp_lib_integer_comparison_functions should have the value 202002L in c++2b"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# else
|
||||
# ifdef __cpp_lib_integer_comparison_functions
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined because it is unimplemented in libc++!"
|
||||
# error "__cpp_lib_integer_comparison_functions should not be defined when defined(__cpp_concepts) && __cpp_concepts >= 201907L is not defined!"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <typename T>
|
||||
struct Tuple {
|
||||
T min;
|
||||
T max;
|
||||
T mid;
|
||||
constexpr Tuple() {
|
||||
min = std::numeric_limits<T>::min();
|
||||
max = std::numeric_limits<T>::max();
|
||||
mid = std::midpoint(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr void test_cmp_equal1() {
|
||||
constexpr Tuple<T> tup;
|
||||
assert(std::cmp_equal(T(0), T(0)));
|
||||
assert(std::cmp_equal(T(10), T(10)));
|
||||
assert(std::cmp_equal(tup.min, tup.min));
|
||||
assert(std::cmp_equal(tup.max, tup.max));
|
||||
assert(!std::cmp_equal(T(0), T(1)));
|
||||
assert(!std::cmp_equal(T(1), T(0)));
|
||||
assert(!std::cmp_equal(T(5), T(10)));
|
||||
assert(!std::cmp_equal(T(10), T(5)));
|
||||
assert(!std::cmp_equal(tup.min, tup.max));
|
||||
assert(!std::cmp_equal(tup.max, tup.min));
|
||||
assert(!std::cmp_equal(1, tup.max));
|
||||
assert(!std::cmp_equal(tup.max, 1));
|
||||
assert(!std::cmp_equal(1, tup.min));
|
||||
assert(!std::cmp_equal(tup.min, 1));
|
||||
assert(std::cmp_equal(T(-5), T(-5)));
|
||||
assert(!std::cmp_equal(-2, tup.min));
|
||||
assert(!std::cmp_equal(tup.min, -2));
|
||||
assert(!std::cmp_equal(-2, tup.max));
|
||||
assert(!std::cmp_equal(tup.max, -2));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr void test_cmp_equal2() {
|
||||
constexpr Tuple<T> ttup;
|
||||
constexpr Tuple<U> utup;
|
||||
assert(std::cmp_equal(T(0), U(0)));
|
||||
assert(std::cmp_equal(T(10), U(10)));
|
||||
assert(!std::cmp_equal(T(0), U(1)));
|
||||
assert(!std::cmp_equal(T(1), U(0)));
|
||||
assert(!std::cmp_equal(T(5), U(10)));
|
||||
assert(!std::cmp_equal(T(10), U(5)));
|
||||
assert(!std::cmp_equal(ttup.min, utup.max));
|
||||
assert(!std::cmp_equal(utup.min, ttup.max));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
constexpr void test1(const std::tuple<Ts...>&) {
|
||||
(test_cmp_equal1<Ts>() , ...);
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
constexpr void test2_impl(const std::tuple<Us...>&) {
|
||||
(test_cmp_equal2<T, Us>() , ...);
|
||||
}
|
||||
|
||||
template <class... Ts, class UTuple>
|
||||
constexpr void test2(const std::tuple<Ts...>&, const UTuple& utuple) {
|
||||
(test2_impl<Ts>(utuple) , ...);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t, __uint128_t,
|
||||
#endif
|
||||
unsigned long long, long long, unsigned long, long, unsigned int, int,
|
||||
unsigned short, short, unsigned char, signed char> types;
|
||||
test1(types);
|
||||
test2(types, types);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ASSERT_NOEXCEPT(std::cmp_equal(0, 0));
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// constexpr bool cmp_greater(T t, U u) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <typename T>
|
||||
struct Tuple {
|
||||
T min;
|
||||
T max;
|
||||
T mid;
|
||||
constexpr Tuple() {
|
||||
min = std::numeric_limits<T>::min();
|
||||
max = std::numeric_limits<T>::max();
|
||||
mid = std::midpoint(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr void test_cmp_greater1() {
|
||||
constexpr Tuple<T> tup;
|
||||
assert(!std::cmp_greater(T(0), T(1)));
|
||||
assert(!std::cmp_greater(T(1), T(2)));
|
||||
assert(!std::cmp_greater(tup.min, tup.max));
|
||||
assert(!std::cmp_greater(tup.min, tup.mid));
|
||||
assert(!std::cmp_greater(tup.mid, tup.max));
|
||||
assert(std::cmp_greater(T(1), T(0)));
|
||||
assert(std::cmp_greater(T(10), T(5)));
|
||||
assert(std::cmp_greater(tup.max, tup.min));
|
||||
assert(std::cmp_greater(tup.mid, tup.min));
|
||||
assert(!std::cmp_greater(tup.mid, tup.mid));
|
||||
assert(!std::cmp_greater(tup.min, tup.min));
|
||||
assert(!std::cmp_greater(tup.max, tup.max));
|
||||
assert(std::cmp_greater(tup.max, 1));
|
||||
assert(std::cmp_greater(1, tup.min));
|
||||
assert(!std::cmp_greater(T(-1), T(-1)));
|
||||
assert(std::cmp_greater(-2, tup.min) == std::is_signed_v<T>);
|
||||
assert(!std::cmp_greater(tup.min, -2) == std::is_signed_v<T>);
|
||||
assert(!std::cmp_greater(-2, tup.max));
|
||||
assert(std::cmp_greater(tup.max, -2));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr void test_cmp_greater2() {
|
||||
assert(!std::cmp_greater(T(0), U(1)));
|
||||
assert(std::cmp_greater(T(1), U(0)));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
constexpr void test1(const std::tuple<Ts...>&) {
|
||||
(test_cmp_greater1<Ts>() , ...);
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
constexpr void test2_impl(const std::tuple<Us...>&) {
|
||||
(test_cmp_greater2<T, Us>() , ...);
|
||||
}
|
||||
|
||||
template <class... Ts, class UTuple>
|
||||
constexpr void test2(const std::tuple<Ts...>&, const UTuple& utuple) {
|
||||
(test2_impl<Ts>(utuple) , ...);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t, __uint128_t,
|
||||
#endif
|
||||
unsigned long long, long long, unsigned long, long, unsigned int, int,
|
||||
unsigned short, short, unsigned char, signed char> types;
|
||||
test1(types);
|
||||
test2(types, types);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ASSERT_NOEXCEPT(std::cmp_greater(1, 0));
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// constexpr bool cmp_greater_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <typename T>
|
||||
struct Tuple {
|
||||
T min;
|
||||
T max;
|
||||
T mid;
|
||||
constexpr Tuple() {
|
||||
min = std::numeric_limits<T>::min();
|
||||
max = std::numeric_limits<T>::max();
|
||||
mid = std::midpoint(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr void test_cmp_greater_equal1() {
|
||||
constexpr Tuple<T> tup;
|
||||
assert(!std::cmp_greater_equal(T(0), T(1)));
|
||||
assert(!std::cmp_greater_equal(T(1), T(2)));
|
||||
assert(!std::cmp_greater_equal(tup.min, tup.max));
|
||||
assert(!std::cmp_greater_equal(tup.min, tup.mid));
|
||||
assert(!std::cmp_greater_equal(tup.mid, tup.max));
|
||||
assert(std::cmp_greater_equal(T(1), T(0)));
|
||||
assert(std::cmp_greater_equal(T(10), T(5)));
|
||||
assert(std::cmp_greater_equal(tup.max, tup.min));
|
||||
assert(std::cmp_greater_equal(tup.mid, tup.min));
|
||||
assert(std::cmp_greater_equal(tup.mid, tup.mid));
|
||||
assert(std::cmp_greater_equal(tup.min, tup.min));
|
||||
assert(std::cmp_greater_equal(tup.max, tup.max));
|
||||
assert(std::cmp_greater_equal(tup.max, 1));
|
||||
assert(std::cmp_greater_equal(1, tup.min));
|
||||
assert(std::cmp_greater_equal(T(-1), T(-1)));
|
||||
assert(std::cmp_greater_equal(-2, tup.min) == std::is_signed_v<T>);
|
||||
assert(std::cmp_greater_equal(tup.min, -2) == std::is_unsigned_v<T>);
|
||||
assert(!std::cmp_greater_equal(-2, tup.max));
|
||||
assert(std::cmp_greater_equal(tup.max, -2));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr void test_cmp_greater_equal2() {
|
||||
assert(!std::cmp_greater_equal(T(0), U(1)));
|
||||
assert(std::cmp_greater_equal(T(1), U(0)));
|
||||
assert(std::cmp_greater_equal(T(0), U(0)));
|
||||
assert(std::cmp_greater_equal(T(1), U(1)));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
constexpr void test1(const std::tuple<Ts...>&) {
|
||||
(test_cmp_greater_equal1<Ts>() , ...);
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
constexpr void test2_impl(const std::tuple<Us...>&) {
|
||||
(test_cmp_greater_equal2<T, Us>() , ...);
|
||||
}
|
||||
|
||||
template <class... Ts, class UTuple>
|
||||
constexpr void test2(const std::tuple<Ts...>&, const UTuple& utuple) {
|
||||
(test2_impl<Ts>(utuple) , ...);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t, __uint128_t,
|
||||
#endif
|
||||
unsigned long long, long long, unsigned long, long, unsigned int, int,
|
||||
unsigned short, short, unsigned char, signed char> types;
|
||||
test1(types);
|
||||
test2(types, types);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ASSERT_NOEXCEPT(std::cmp_greater_equal(1, 0));
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_less(T t, U u) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <typename T>
|
||||
struct Tuple {
|
||||
T min;
|
||||
T max;
|
||||
T mid;
|
||||
constexpr Tuple() {
|
||||
min = std::numeric_limits<T>::min();
|
||||
max = std::numeric_limits<T>::max();
|
||||
mid = std::midpoint(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr void test_cmp_less1() {
|
||||
constexpr Tuple<T> tup;
|
||||
assert(std::cmp_less(T(0), T(1)));
|
||||
assert(std::cmp_less(T(1), T(2)));
|
||||
assert(std::cmp_less(tup.min, tup.max));
|
||||
assert(std::cmp_less(tup.min, tup.mid));
|
||||
assert(std::cmp_less(tup.mid, tup.max));
|
||||
assert(!std::cmp_less(T(1), T(0)));
|
||||
assert(!std::cmp_less(T(10), T(5)));
|
||||
assert(!std::cmp_less(tup.max, tup.min));
|
||||
assert(!std::cmp_less(tup.mid, tup.min));
|
||||
assert(!std::cmp_less(tup.mid, tup.mid));
|
||||
assert(!std::cmp_less(tup.min, tup.min));
|
||||
assert(!std::cmp_less(tup.max, tup.max));
|
||||
assert(!std::cmp_less(tup.max, 1));
|
||||
assert(!std::cmp_less(1, tup.min));
|
||||
assert(!std::cmp_less(T(-1), T(-1)));
|
||||
assert(!std::cmp_less(-2, tup.min) == std::is_signed_v<T>);
|
||||
assert(std::cmp_less(tup.min, -2) == std::is_signed_v<T>);
|
||||
assert(std::cmp_less(-2, tup.max));
|
||||
assert(!std::cmp_less(tup.max, -2));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr void test_cmp_less2() {
|
||||
assert(std::cmp_less(T(0), U(1)));
|
||||
assert(!std::cmp_less(T(1), U(0)));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
constexpr void test1(const std::tuple<Ts...>&) {
|
||||
(test_cmp_less1<Ts>() , ...);
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
constexpr void test2_impl(const std::tuple<Us...>&) {
|
||||
(test_cmp_less2<T, Us>() , ...);
|
||||
}
|
||||
|
||||
template <class... Ts, class UTuple>
|
||||
constexpr void test2(const std::tuple<Ts...>&, const UTuple& utuple) {
|
||||
(test2_impl<Ts>(utuple) , ...);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t, __uint128_t,
|
||||
#endif
|
||||
unsigned long long, long long, unsigned long, long, unsigned int, int,
|
||||
unsigned short, short, unsigned char, signed char> types;
|
||||
test1(types);
|
||||
test2(types, types);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ASSERT_NOEXCEPT(std::cmp_less(0, 1));
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// constexpr bool cmp_less_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <typename T>
|
||||
struct Tuple {
|
||||
T min;
|
||||
T max;
|
||||
T mid;
|
||||
constexpr Tuple() {
|
||||
min = std::numeric_limits<T>::min();
|
||||
max = std::numeric_limits<T>::max();
|
||||
mid = std::midpoint(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr void test_cmp_less_equal1() {
|
||||
constexpr Tuple<T> tup;
|
||||
assert(std::cmp_less_equal(T(0), T(0)));
|
||||
assert(std::cmp_less_equal(T(0), T(1)));
|
||||
assert(std::cmp_less_equal(tup.min, tup.max));
|
||||
assert(std::cmp_less_equal(tup.min, tup.mid));
|
||||
assert(std::cmp_less_equal(tup.mid, tup.max));
|
||||
assert(std::cmp_less_equal(tup.max, tup.max));
|
||||
assert(std::cmp_less_equal(tup.mid, tup.mid));
|
||||
assert(std::cmp_less_equal(tup.min, tup.min));
|
||||
assert(!std::cmp_less_equal(T(1), T(0)));
|
||||
assert(!std::cmp_less_equal(T(10), T(5)));
|
||||
assert(!std::cmp_less_equal(tup.max, tup.min));
|
||||
assert(!std::cmp_less_equal(tup.mid, tup.min));
|
||||
assert(!std::cmp_less_equal(tup.max, 1));
|
||||
assert(!std::cmp_less_equal(1, tup.min));
|
||||
assert(std::cmp_less_equal(T(-1), T(-1)));
|
||||
assert(!std::cmp_less_equal(-2, tup.min) == std::is_signed_v<T>);
|
||||
assert(std::cmp_less_equal(tup.min, -2) == std::is_signed_v<T>);
|
||||
assert(std::cmp_less_equal(-2, tup.max));
|
||||
assert(!std::cmp_less_equal(tup.max, -2));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr void test_cmp_less_equal2() {
|
||||
assert(std::cmp_less_equal(T(0), U(1)));
|
||||
assert(std::cmp_less_equal(T(0), U(0)));
|
||||
assert(!std::cmp_less_equal(T(1), U(0)));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
constexpr void test1(const std::tuple<Ts...>&) {
|
||||
(test_cmp_less_equal1<Ts>() , ...);
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
constexpr void test2_impl(const std::tuple<Us...>&) {
|
||||
(test_cmp_less_equal2<T, Us>() , ...);
|
||||
}
|
||||
|
||||
template <class... Ts, class UTuple>
|
||||
constexpr void test2(const std::tuple<Ts...>&, const UTuple& utuple) {
|
||||
(test2_impl<Ts>(utuple) , ...);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t, __uint128_t,
|
||||
#endif
|
||||
unsigned long long, long long, unsigned long, long, unsigned int, int,
|
||||
unsigned short, short, unsigned char, signed char> types;
|
||||
test1(types);
|
||||
test2(types, types);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ASSERT_NOEXCEPT(std::cmp_less_equal(0, 1));
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_not_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <typename T>
|
||||
struct Tuple {
|
||||
T min;
|
||||
T max;
|
||||
T mid;
|
||||
constexpr Tuple() {
|
||||
min = std::numeric_limits<T>::min();
|
||||
max = std::numeric_limits<T>::max();
|
||||
mid = std::midpoint(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr void test_cmp_not_equal1() {
|
||||
constexpr Tuple<T> tup;
|
||||
assert(!std::cmp_not_equal(T(0), T(0)));
|
||||
assert(!std::cmp_not_equal(T(10), T(10)));
|
||||
assert(!std::cmp_not_equal(tup.min, tup.min));
|
||||
assert(!std::cmp_not_equal(tup.max, tup.max));
|
||||
assert(std::cmp_not_equal(T(0), T(1)));
|
||||
assert(std::cmp_not_equal(T(1), T(0)));
|
||||
assert(std::cmp_not_equal(T(5), T(10)));
|
||||
assert(std::cmp_not_equal(T(10), T(5)));
|
||||
assert(std::cmp_not_equal(tup.min, tup.max));
|
||||
assert(std::cmp_not_equal(tup.max, tup.min));
|
||||
assert(std::cmp_not_equal(1, tup.max));
|
||||
assert(std::cmp_not_equal(tup.max, 1));
|
||||
assert(std::cmp_not_equal(1, tup.min));
|
||||
assert(std::cmp_not_equal(tup.min, 1));
|
||||
assert(std::cmp_not_equal(-2, tup.min));
|
||||
assert(std::cmp_not_equal(tup.min, -2));
|
||||
assert(std::cmp_not_equal(-2, tup.max));
|
||||
assert(std::cmp_not_equal(tup.max, -2));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr void test_cmp_not_equal2() {
|
||||
constexpr Tuple<T> ttup;
|
||||
constexpr Tuple<U> utup;
|
||||
assert(!std::cmp_not_equal(T(0), U(0)));
|
||||
assert(!std::cmp_not_equal(T(10), U(10)));
|
||||
assert(std::cmp_not_equal(T(0), U(1)));
|
||||
assert(std::cmp_not_equal(T(1), U(0)));
|
||||
assert(std::cmp_not_equal(T(5), U(10)));
|
||||
assert(std::cmp_not_equal(T(10), U(5)));
|
||||
assert(std::cmp_not_equal(ttup.min, utup.max));
|
||||
assert(std::cmp_not_equal(utup.min, ttup.max));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
constexpr void test1(const std::tuple<Ts...>&) {
|
||||
(test_cmp_not_equal1<Ts>() , ...);
|
||||
}
|
||||
|
||||
template <class T, class... Us>
|
||||
constexpr void test2_impl(const std::tuple<Us...>&) {
|
||||
(test_cmp_not_equal2<T, Us>() , ...);
|
||||
}
|
||||
|
||||
template <class... Ts, class UTuple>
|
||||
constexpr void test2(const std::tuple<Ts...>&, const UTuple& utuple) {
|
||||
(test2_impl<Ts>(utuple) , ...);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t, __uint128_t,
|
||||
#endif
|
||||
unsigned long long, long long, unsigned long, long, unsigned int, int,
|
||||
unsigned short, short, unsigned char, signed char> types;
|
||||
test1(types);
|
||||
test2(types, types);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ASSERT_NOEXCEPT(std::cmp_not_equal(0, 0));
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_not_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_less(T t, U u) noexcept; // C++20
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_less_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_greater(T t, U u) noexcept; // C++20
|
||||
|
||||
// template<class T, class U>
|
||||
// constexpr bool cmp_greater_equal(T t, U u) noexcept; // C++20
|
||||
|
||||
// template<class R, class T>
|
||||
// constexpr bool in_range(T t) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NonEmptyT {
|
||||
int val;
|
||||
NonEmptyT() : val(0) {}
|
||||
NonEmptyT(int val) : val(val) {}
|
||||
operator int&() { return val; }
|
||||
operator int() const { return val; }
|
||||
};
|
||||
|
||||
enum ColorT { red, green, blue };
|
||||
|
||||
struct EmptyT {};
|
||||
|
||||
template <class T>
|
||||
constexpr void test() {
|
||||
std::cmp_equal(T(), T()); // expected-error11{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_equal(T(), int()); // expected-error11{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_equal(int(), T()); // expected-error11{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_not_equal(T(), T()); // expected-error11{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_not_equal(T(), int()); // expected-error11{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_not_equal(int(), T()); // expected-error11{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_less(T(), T()); // expected-error11{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less(T(), int()); // expected-error11{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less(int(), T()); // expected-error11{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less_equal(T(), T()); // expected-error11{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_less_equal(T(), int()); // expected-error11{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_less_equal(int(), T()); // expected-error11{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_greater(T(), T()); // expected-error11{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater(T(), int()); // expected-error11{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater(int(), T()); // expected-error11{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater_equal(T(), T()); // expected-error11{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::cmp_greater_equal(T(), int()); // expected-error11{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::cmp_greater_equal(int(), T()); // expected-error11{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::in_range<T>(int()); // expected-error11{{no matching function for call to 'in_range'}}
|
||||
std::in_range<int>(T()); // expected-error11{{no matching function for call to 'in_range'}}
|
||||
}
|
||||
#ifndef _LIBCPP_NO_HAS_CHAR8_T
|
||||
template <class T>
|
||||
constexpr void test_char8t() {
|
||||
std::cmp_equal(T(), T()); // expected-error1{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_equal(T(), int()); // expected-error1{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_equal(int(), T()); // expected-error1{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_not_equal(T(), T()); // expected-error1{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_not_equal(T(), int()); // expected-error1{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_not_equal(int(), T()); // expected-error1{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_less(T(), T()); // expected-error1{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less(T(), int()); // expected-error1{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less(int(), T()); // expected-error1{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less_equal(T(), T()); // expected-error1{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_less_equal(T(), int()); // expected-error1{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_less_equal(int(), T()); // expected-error1{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_greater(T(), T()); // expected-error1{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater(T(), int()); // expected-error1{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater(int(), T()); // expected-error1{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater_equal(T(), T()); // expected-error1{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::cmp_greater_equal(T(), int()); // expected-error1{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::cmp_greater_equal(int(), T()); // expected-error1{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::in_range<T>(int()); // expected-error1{{no matching function for call to 'in_range'}}
|
||||
std::in_range<int>(T()); // expected-error1{{no matching function for call to 'in_range'}}
|
||||
}
|
||||
#endif // _LIBCPP_NO_HAS_CHAR8_T
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
template <class T>
|
||||
constexpr void test_uchars() {
|
||||
std::cmp_equal(T(), T()); // expected-error2{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_equal(T(), int()); // expected-error2{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_equal(int(), T()); // expected-error2{{no matching function for call to 'cmp_equal'}}
|
||||
std::cmp_not_equal(T(), T()); // expected-error2{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_not_equal(T(), int()); // expected-error2{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_not_equal(int(), T()); // expected-error2{{no matching function for call to 'cmp_not_equal'}}
|
||||
std::cmp_less(T(), T()); // expected-error2{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less(T(), int()); // expected-error2{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less(int(), T()); // expected-error2{{no matching function for call to 'cmp_less'}}
|
||||
std::cmp_less_equal(T(), T()); // expected-error2{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_less_equal(T(), int()); // expected-error2{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_less_equal(int(), T()); // expected-error2{{no matching function for call to 'cmp_less_equal'}}
|
||||
std::cmp_greater(T(), T()); // expected-error2{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater(T(), int()); // expected-error2{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater(int(), T()); // expected-error2{{no matching function for call to 'cmp_greater'}}
|
||||
std::cmp_greater_equal(T(), T()); // expected-error2{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::cmp_greater_equal(T(), int()); // expected-error2{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::cmp_greater_equal(int(), T()); // expected-error2{{no matching function for call to 'cmp_greater_equal'}}
|
||||
std::in_range<T>(int()); // expected-error2{{no matching function for call to 'in_range'}}
|
||||
std::in_range<int>(T()); // expected-error2{{no matching function for call to 'in_range'}}
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
|
||||
int main() {
|
||||
test<bool>();
|
||||
test<char>();
|
||||
test<wchar_t>();
|
||||
test<float>();
|
||||
test<double>();
|
||||
test<long double>();
|
||||
test<std::byte>();
|
||||
test<NonEmptyT>();
|
||||
test<ColorT>();
|
||||
test<nullptr_t>();
|
||||
test<EmptyT>();
|
||||
#ifndef _LIBCPP_NO_HAS_CHAR8_T
|
||||
test_char8t<char8_t>();
|
||||
#endif // !_LIBCPP_NO_HAS_CHAR8_T
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
test_uchars<char16_t>();
|
||||
test_uchars<char32_t>();
|
||||
#endif // !_LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <utility>
|
||||
|
||||
// template<class R, class T>
|
||||
// constexpr bool in_range(T t) noexcept; // C++20
|
||||
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <typename T>
|
||||
struct Tuple {
|
||||
T min;
|
||||
T max;
|
||||
T mid;
|
||||
constexpr Tuple() {
|
||||
min = std::numeric_limits<T>::min();
|
||||
max = std::numeric_limits<T>::max();
|
||||
mid = std::midpoint(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr void test_in_range1() {
|
||||
constexpr Tuple<T> tup;
|
||||
assert(std::in_range<T>(tup.min));
|
||||
assert(std::in_range<T>(tup.min + 1));
|
||||
assert(std::in_range<T>(tup.max));
|
||||
assert(std::in_range<T>(tup.max - 1));
|
||||
assert(std::in_range<T>(tup.mid));
|
||||
assert(std::in_range<T>(tup.mid - 1));
|
||||
assert(std::in_range<T>(tup.mid + 1));
|
||||
}
|
||||
|
||||
constexpr void test_in_range() {
|
||||
constexpr Tuple<uint8_t> utup8;
|
||||
constexpr Tuple<int8_t> stup8;
|
||||
assert(!std::in_range<int8_t>(utup8.max));
|
||||
assert(std::in_range<short>(utup8.max));
|
||||
assert(!std::in_range<uint8_t>(stup8.min));
|
||||
assert(std::in_range<int8_t>(utup8.mid));
|
||||
assert(!std::in_range<uint8_t>(stup8.mid));
|
||||
assert(!std::in_range<uint8_t>(-1));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
constexpr void test1(const std::tuple<Ts...>&) {
|
||||
(test_in_range1<Ts>() , ...);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t, __uint128_t,
|
||||
#endif
|
||||
unsigned long long, long long, unsigned long, long, unsigned int, int,
|
||||
unsigned short, short, unsigned char, signed char> types;
|
||||
test1(types);
|
||||
test_in_range();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ASSERT_NOEXCEPT(std::in_range<int>(-1));
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
|
@ -340,7 +340,8 @@ feature_test_macros = [ add_version_header(x) for x in [
|
|||
"name": "__cpp_lib_integer_comparison_functions",
|
||||
"values": { "c++20": 202002 },
|
||||
"headers": ["utility"],
|
||||
"unimplemented": True,
|
||||
"test_suite_guard": "defined(__cpp_concepts) && __cpp_concepts >= 201907L",
|
||||
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_CONCEPTS)",
|
||||
}, {
|
||||
"name": "__cpp_lib_integer_sequence",
|
||||
"values": { "c++14": 201304 },
|
||||
|
|
Loading…
Reference in New Issue