diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 0260da13c88..541258019c2 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -471,12 +471,17 @@ struct _Is_default_allocator, void_t::_Fr : is_same::_From_primary, allocator<_Ty>>::type {}; #if _HAS_CXX23 +#ifdef __cpp_lib_concepts // TRANSITION, GH-395 +template +concept _Has_member_allocate_at_least = requires(_Alloc& _Al, const _SizeTy& _Count) { _Al.allocate_at_least(_Count); }; +#else // ^^^ no workaround / workaround vvv template inline constexpr bool _Has_member_allocate_at_least = false; template inline constexpr bool _Has_member_allocate_at_least<_Alloc, _SizeTy, void_t().allocate_at_least(_STD declval()))>> = true; +#endif // __cpp_lib_concepts #endif // _HAS_CXX23 template diff --git a/tests/std/tests/GH_003570_allocate_at_least/test.cpp b/tests/std/tests/GH_003570_allocate_at_least/test.cpp index 05a5f45cf52..1814ff4e2bd 100644 --- a/tests/std/tests/GH_003570_allocate_at_least/test.cpp +++ b/tests/std/tests/GH_003570_allocate_at_least/test.cpp @@ -122,6 +122,31 @@ void test_inheriting_allocator() { assert(accumulate(vec.begin(), vec.end(), 0, plus<>{}) == 36); } +// Also test GH-3890, in which we incorrectly tried to use allocate_at_least from an inaccessible std::allocator +// base due to an MSVC bug. +template +struct less_icky_allocator : private allocator { + using value_type = T; + + less_icky_allocator() = default; + template + less_icky_allocator(const less_icky_allocator&) {} + + T* allocate(size_t n) { + return allocator::allocate(n); + } + + void deallocate(T* ptr, size_t n) { + return allocator::deallocate(ptr, n); + } + + template + bool operator==(const less_icky_allocator&) const { + return true; + } +}; +static_assert(!std::_Should_allocate_at_least>); + int main() { test_deque(); test_container, signalling_allocator>>();