Skip to content

Commit c37734d

Browse files
[libc++] Fix ability to explicitly instantiate std::midpoint (llvm#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 llvm#67046
1 parent d5abd8a commit c37734d

File tree

3 files changed

+12
-10
lines changed

3 files changed

+12
-10
lines changed

libcxx/include/__numeric/midpoint.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,8 @@ midpoint(_Tp __a, _Tp __b) noexcept _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
4848
return __a + __half_diff;
4949
}
5050

51-
template <class _TPtr>
52-
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
53-
is_pointer_v<_TPtr> && is_object_v<remove_pointer_t<_TPtr>> && !is_void_v<remove_pointer_t<_TPtr>> &&
54-
(sizeof(remove_pointer_t<_TPtr>) > 0),
55-
_TPtr>
56-
midpoint(_TPtr __a, _TPtr __b) noexcept {
51+
template <class _Tp, enable_if_t<is_object_v<_Tp> && !is_void_v<_Tp> && (sizeof(_Tp) > 0), int> = 0>
52+
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* midpoint(_Tp* __a, _Tp* __b) noexcept {
5753
return __a + std::midpoint(ptrdiff_t(0), __b - __a);
5854
}
5955

libcxx/test/libcxx/numerics/numeric.ops/midpoint.integer.pass.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222

2323
// Users are not supposed to provide template argument lists for
2424
// functions in the standard library (there's an exception for min and max)
25-
// However, libc++ protects against this for pointers, so we check to make
26-
// sure that our protection is working here.
27-
// In some cases midpoint<int>(0,0) might get deduced as the pointer overload.
25+
// However, libc++ protects against this for pointers. The use of T(0)
26+
// in the test cases resolves potential ambiguity in template argument deduction
27+
// for the std::midpoint function.
2828

2929
template <typename T>
3030
void test()
3131
{
32-
ASSERT_SAME_TYPE(T, decltype(std::midpoint<T>(0, 0)));
32+
ASSERT_SAME_TYPE(T, decltype(std::midpoint<T>(T(0), T(0))));
3333
}
3434

3535
int main(int, char**)

libcxx/test/std/numerics/numeric.ops/numeric.ops.midpoint/midpoint.pointer.pass.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ void runtime_test()
5454
assert(std::midpoint(array + 9, array) == array + 5);
5555
assert(std::midpoint(array + 10, array) == array + 5);
5656
assert(std::midpoint(array + 11, array) == array + 6);
57+
58+
// explicit instantiation
59+
ASSERT_SAME_TYPE(decltype(std::midpoint<T>(array, array)), T*);
60+
ASSERT_NOEXCEPT(std::midpoint<T>(array, array));
61+
assert(std::midpoint<T>(array, array) == array);
62+
assert(std::midpoint<T>(array, array + 1000) == array + 500);
5763
}
5864

5965
template <typename T>

0 commit comments

Comments
 (0)