Skip to content

Commit

Permalink
[libc++] Fix ability to explicitly instantiate std::midpoint (llvm#74217
Browse files Browse the repository at this point in the history
)

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 llvm#67046
  • Loading branch information
SanjayMarreddi committed Dec 20, 2023
1 parent d5abd8a commit c37734d
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 10 deletions.
8 changes: 2 additions & 6 deletions libcxx/include/__numeric/midpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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**)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down

0 comments on commit c37734d

Please sign in to comment.