[libc++] Fix ability to explicitly instantiate std::midpoint (#74217)

std::midpoint is specified by having a pointer overload in
[numeric.ops.midpoint].
With the way the pointer overload is specified, users can expect that
calling
std::midpoint as `std::midpoint<T>(a, b)` should work, but it didn't in
libc++
due to the way the pointer overload was specified.

Fixes #67046
This commit is contained in:
Sanjay Marreddi 2023-12-20 10:53:19 +00:00 committed by GitHub
parent d5abd8a1a9
commit c37734d409
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 10 deletions

View File

@ -48,12 +48,8 @@ midpoint(_Tp __a, _Tp __b) noexcept _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
return __a + __half_diff;
}
template <class _TPtr>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_pointer_v<_TPtr> && is_object_v<remove_pointer_t<_TPtr>> && !is_void_v<remove_pointer_t<_TPtr>> &&
(sizeof(remove_pointer_t<_TPtr>) > 0),
_TPtr>
midpoint(_TPtr __a, _TPtr __b) noexcept {
template <class _Tp, enable_if_t<is_object_v<_Tp> && !is_void_v<_Tp> && (sizeof(_Tp) > 0), int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* midpoint(_Tp* __a, _Tp* __b) noexcept {
return __a + std::midpoint(ptrdiff_t(0), __b - __a);
}

View File

@ -22,14 +22,14 @@
// Users are not supposed to provide template argument lists for
// functions in the standard library (there's an exception for min and max)
// However, libc++ protects against this for pointers, so we check to make
// sure that our protection is working here.
// In some cases midpoint<int>(0,0) might get deduced as the pointer overload.
// However, libc++ protects against this for pointers. The use of T(0)
// in the test cases resolves potential ambiguity in template argument deduction
// for the std::midpoint function.
template <typename T>
void test()
{
ASSERT_SAME_TYPE(T, decltype(std::midpoint<T>(0, 0)));
ASSERT_SAME_TYPE(T, decltype(std::midpoint<T>(T(0), T(0))));
}
int main(int, char**)

View File

@ -54,6 +54,12 @@ void runtime_test()
assert(std::midpoint(array + 9, array) == array + 5);
assert(std::midpoint(array + 10, array) == array + 5);
assert(std::midpoint(array + 11, array) == array + 6);
// explicit instantiation
ASSERT_SAME_TYPE(decltype(std::midpoint<T>(array, array)), T*);
ASSERT_NOEXCEPT(std::midpoint<T>(array, array));
assert(std::midpoint<T>(array, array) == array);
assert(std::midpoint<T>(array, array + 1000) == array + 500);
}
template <typename T>