int> = 0>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) {
- return std::__constexpr_memcmp_equal(__first1, __first2, (__last1 - __first1) * sizeof(_Tp));
+ return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
}
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
int> = 0>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
- return std::__constexpr_memcmp_equal(__first1, __first2, (__last1 - __first1) * sizeof(_Tp));
+ return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
}
template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>
_LIBCPP_BEGIN_NAMESPACE_STD
+// Type used to encode that a function takes an integer that represents a number
+// of elements as opposed to a number of bytes.
+enum class __element_count : size_t {};
+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) {
// GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816
// of invoking it on every object individually.
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
-__constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, size_t __count) {
+__constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
static_assert(__libcpp_is_trivially_lexicographically_comparable<_Tp, _Up>::value,
"_Tp and _Up have to be trivially lexicographically comparable");
+ auto __count = static_cast<size_t>(__n);
+
if (__libcpp_is_constant_evaluated()) {
#ifdef _LIBCPP_COMPILER_CLANG_BASED
if (sizeof(_Tp) == 1 && !is_same<_Tp, bool>::value)
- return __builtin_memcmp(__lhs, __rhs, __count);
+ return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
#endif
while (__count != 0) {
if (*__rhs < *__lhs)
return 1;
- __count -= sizeof(_Tp);
+ --__count;
++__lhs;
++__rhs;
}
return 0;
} else {
- return __builtin_memcmp(__lhs, __rhs, __count);
+ return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
}
}
// of invoking it on every object individually.
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
-__constexpr_memcmp_equal(const _Tp* __lhs, const _Up* __rhs, size_t __count) {
+__constexpr_memcmp_equal(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
static_assert(__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
"_Tp and _Up have to be trivially equality comparable");
+ auto __count = static_cast<size_t>(__n);
+
if (__libcpp_is_constant_evaluated()) {
#ifdef _LIBCPP_COMPILER_CLANG_BASED
if (sizeof(_Tp) == 1 && is_integral<_Tp>::value && !is_same<_Tp, bool>::value)
- return __builtin_memcmp(__lhs, __rhs, __count) == 0;
+ return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
#endif
while (__count != 0) {
if (*__lhs != *__rhs)
return false;
- __count -= sizeof(_Tp);
+ --__count;
++__lhs;
++__rhs;
}
return true;
} else {
- return __builtin_memcmp(__lhs, __rhs, __count) == 0;
+ return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0;
}
}
constexpr unsigned char Bananf[] = "Bananf";
static_assert(std::__constexpr_strlen("Banane") == 6, "");
-static_assert(std::__constexpr_memcmp(Banane, Banand, 6) == 1, "");
-static_assert(std::__constexpr_memcmp(Banane, Banane, 6) == 0, "");
-static_assert(std::__constexpr_memcmp(Banane, Bananf, 6) == -1, "");
+static_assert(std::__constexpr_memcmp(Banane, Banand, std::__element_count(6)) == 1, "");
+static_assert(std::__constexpr_memcmp(Banane, Banane, std::__element_count(6)) == 0, "");
+static_assert(std::__constexpr_memcmp(Banane, Bananf, std::__element_count(6)) == -1, "");
-static_assert(!std::__constexpr_memcmp_equal(Banane, Banand, 6), "");
-static_assert(std::__constexpr_memcmp_equal(Banane, Banane, 6), "");
+static_assert(!std::__constexpr_memcmp_equal(Banane, Banand, std::__element_count(6)), "");
+static_assert(std::__constexpr_memcmp_equal(Banane, Banane, std::__element_count(6)), "");
constexpr bool test_constexpr_wmemchr() {