`<list>`, `<string>`: Remove allocator-moving tagged internal constructors (#4976)

Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
This commit is contained in:
A. Jiang 2024-09-29 04:16:15 +08:00 коммит произвёл GitHub
Родитель 722e1507c8
Коммит 1c3e0d6509
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
7 изменённых файлов: 105 добавлений и 18 удалений

Просмотреть файл

@ -751,6 +751,10 @@ private:
template <class _Traits>
class _Hash;
struct _Move_allocator_tag {
explicit _Move_allocator_tag() = default;
};
_EXPORT_STD template <class _Ty, class _Alloc = allocator<_Ty>>
class list { // bidirectional linked list
private:
@ -804,8 +808,8 @@ public:
}
private:
template <class _Any_alloc>
explicit list(_Move_allocator_tag, _Any_alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _STD move(_Al)) {
template <class _Tag, class _Any_alloc, enable_if_t<is_same_v<_Tag, _Move_allocator_tag>, int> = 0>
explicit list(_Tag, _Any_alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _STD move(_Al)) {
_Alloc_sentinel_and_proxy();
}

Просмотреть файл

@ -239,7 +239,7 @@ public:
// the buffer may already be full, and the terminating char is not '\0'.
// In that case, copy the string as usual.
_NODISCARD _Mystr str() && {
_Mystr _Result{_String_constructor_rvalue_allocator_tag{}, _STD move(_Al)};
_Mystr _Result{_Al};
const auto _View = _Get_buffer_view();
// _Size cannot be larger than _Res, but it could be equal,
// because basic_stringbuf doesn't allocate for the terminating '\0'.

Просмотреть файл

@ -1535,10 +1535,6 @@ public:
}
};
struct _Move_allocator_tag {
explicit _Move_allocator_tag() = default;
};
template <class _Ty>
pair<_Ty*, ptrdiff_t> _Get_temporary_buffer(ptrdiff_t _Count) noexcept {
if (static_cast<size_t>(_Count) <= static_cast<size_t>(-1) / sizeof(_Ty)) {

Просмотреть файл

@ -508,11 +508,6 @@ struct _String_constructor_concat_tag {
explicit _String_constructor_concat_tag() = default;
};
struct _String_constructor_rvalue_allocator_tag {
// tag to select constructors used by basic_stringbuf's rvalue str()
explicit _String_constructor_rvalue_allocator_tag() = default;
};
[[noreturn]] inline void _Xlen_string() {
_Xlength_error("string too long");
}
@ -1145,12 +1140,6 @@ public:
#endif // _HAS_CXX17
#if _HAS_CXX20
basic_string(_String_constructor_rvalue_allocator_tag, _Alloc&& _Al)
: _Mypair(_One_then_variadic_args_t{}, _STD move(_Al)) {
// Used exclusively by basic_stringbuf
_Construct_empty();
}
_NODISCARD bool _Move_assign_from_buffer(
_Elem* const _Right, const size_type _Size, const size_type _Actual_allocation_size) {
// Move assign from a buffer, used exclusively by basic_stringbuf; returns _Large_mode_engaged()

Просмотреть файл

@ -250,6 +250,7 @@ tests\GH_004618_mixed_operator_usage_keeps_statistical_properties
tests\GH_004618_normal_distribution_avoids_resets
tests\GH_004657_expected_constraints_permissive
tests\GH_004845_logical_operator_traits_with_non_bool_constant
tests\GH_004929_internal_tag_constructors
tests\GH_004930_char_traits_user_specialization
tests\LWG2381_num_get_floating_point
tests\LWG2597_complex_branch_cut

Просмотреть файл

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\impure_matrix.lst

Просмотреть файл

@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <cassert>
#include <list>
#include <memory>
#include <string>
#include <type_traits>
#if _HAS_CXX17
#include <string_view>
#endif // _HAS_CXX17
#if _HAS_CXX20
#define CONSTEXPR20 constexpr
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
#define CONSTEXPR20 inline
#endif // ^^^ !_HAS_CXX20 ^^^
using namespace std;
template <class>
constexpr bool is_initializer_list = false;
template <class T>
constexpr bool is_initializer_list<initializer_list<T>> = true;
template <class T>
constexpr initializer_list<T> ilist42 = {T{'4'}, T{'2'}};
template <class>
constexpr bool is_basic_string_or_cstr_or_view = false;
template <class C, class T, class A>
constexpr bool is_basic_string_or_cstr_or_view<basic_string<C, T, A>> = true;
template <class C>
constexpr bool is_basic_string_or_cstr_or_view<const C*> = true;
#if _HAS_CXX17
template <class C, class T>
constexpr bool is_basic_string_or_cstr_or_view<basic_string_view<C, T>> = true;
#endif // _HAS_CXX17
struct nasty_string_source {
template <class IList, enable_if_t<is_initializer_list<IList>, int> = 0>
constexpr operator IList() const {
return ilist42<typename IList::value_type>;
}
template <class T, enable_if_t<!is_initializer_list<T> && !is_basic_string_or_cstr_or_view<T>, int> = 0>
constexpr operator T() const {
return T{};
}
};
CONSTEXPR20 bool test_nasty_conversion_to_basic_string() {
assert(string(nasty_string_source{}, allocator<char>{}) == "42"s);
#ifdef __cpp_char8_t
assert(u8string(nasty_string_source{}, allocator<char8_t>{}) == u8"42"s);
#endif // defined(__cpp_char8_t)
assert(u16string(nasty_string_source{}, allocator<char16_t>{}) == u"42"s);
assert(u32string(nasty_string_source{}, allocator<char32_t>{}) == U"42"s);
assert(wstring(nasty_string_source{}, allocator<wchar_t>{}) == L"42"s);
return true;
}
template <class>
constexpr bool is_list = false;
template <class T, class A>
constexpr bool is_list<list<T, A>> = true;
struct nasty_list_source {
template <class IList, enable_if_t<is_initializer_list<IList>, int> = 0>
constexpr operator IList() const {
return ilist42<typename IList::value_type>;
}
template <class T, enable_if_t<!is_initializer_list<T> && !is_list<T> && !is_integral_v<T>, int> = 0>
constexpr operator T() const {
return T{};
}
};
void test_nasty_conversion_to_list() {
allocator<int> ator{};
assert((list<int>{nasty_list_source{}, ator} == list<int>{int{'4'}, int{'2'}}));
}
#if _HAS_CXX20
static_assert(test_nasty_conversion_to_basic_string());
#endif // _HAS_CXX20
int main() {
test_nasty_conversion_to_basic_string();
test_nasty_conversion_to_list();
}