forked from OSchip/llvm-project
[libc++] Implement P1165R1 (Make stateful allocator propagation more consistent)
Reviewed By: Quuxplusone, ldionne, #libc Spies: libcxx-commits Differential Revision: https://reviews.llvm.org/D119112
This commit is contained in:
parent
a7b9af7872
commit
1cfa485769
|
@ -39,6 +39,7 @@ New Features
|
|||
------------
|
||||
|
||||
- Implemented P0627R6 (Function to mark unreachable code)
|
||||
- Implemented P1165R1 (Make stateful allocator propagation more consistent for operator+(basic_string))
|
||||
|
||||
API Changes
|
||||
-----------
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
"`P1085R2 <https://wg21.link/P1085R2>`__","LWG","Should Span be Regular?","San Diego","|Complete|","8.0"
|
||||
"`P1123R0 <https://wg21.link/P1123R0>`__","LWG","Editorial Guidance for merging P0019r8 and P0528r3","San Diego","* *",""
|
||||
"`P1148R0 <https://wg21.link/P1148R0>`__","LWG","Cleaning up Clause 20","San Diego","* *",""
|
||||
"`P1165R1 <https://wg21.link/P1165R1>`__","LWG","Make stateful allocator propagation more consistent for ``operator+(basic_string)``\ ","San Diego","* *",""
|
||||
"`P1165R1 <https://wg21.link/P1165R1>`__","LWG","Make stateful allocator propagation more consistent for ``operator+(basic_string)``\ ","San Diego","|Complete|","15.0"
|
||||
"`P1209R0 <https://wg21.link/P1209R0>`__","LWG","Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20","San Diego","|Complete|","8.0"
|
||||
"`P1210R0 <https://wg21.link/P1210R0>`__","LWG","Completing the Rebase of Library Fundamentals, Version 3, Working Draft","San Diego","* *",""
|
||||
"`P1236R1 <https://wg21.link/P1236R1>`__","CWG","Alternative Wording for P0907R4 Signed Integers are Two's Complement","San Diego","* *",""
|
||||
|
|
|
|
@ -4161,9 +4161,10 @@ basic_string<_CharT, _Traits, _Allocator>
|
|||
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
|
||||
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
|
||||
{
|
||||
basic_string<_CharT, _Traits, _Allocator> __r(__lhs.get_allocator());
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = __lhs.size();
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = __rhs.size();
|
||||
using _String = basic_string<_CharT, _Traits, _Allocator>;
|
||||
_String __r(_String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
|
||||
typename _String::size_type __lhs_sz = __lhs.size();
|
||||
typename _String::size_type __rhs_sz = __rhs.size();
|
||||
__r.__init(__lhs.data(), __lhs_sz, __lhs_sz + __rhs_sz);
|
||||
__r.append(__rhs.data(), __rhs_sz);
|
||||
return __r;
|
||||
|
@ -4173,9 +4174,10 @@ template<class _CharT, class _Traits, class _Allocator>
|
|||
basic_string<_CharT, _Traits, _Allocator>
|
||||
operator+(const _CharT* __lhs , const basic_string<_CharT,_Traits,_Allocator>& __rhs)
|
||||
{
|
||||
basic_string<_CharT, _Traits, _Allocator> __r(__rhs.get_allocator());
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = _Traits::length(__lhs);
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = __rhs.size();
|
||||
using _String = basic_string<_CharT, _Traits, _Allocator>;
|
||||
_String __r(_String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
|
||||
typename _String::size_type __lhs_sz = _Traits::length(__lhs);
|
||||
typename _String::size_type __rhs_sz = __rhs.size();
|
||||
__r.__init(__lhs, __lhs_sz, __lhs_sz + __rhs_sz);
|
||||
__r.append(__rhs.data(), __rhs_sz);
|
||||
return __r;
|
||||
|
@ -4185,8 +4187,9 @@ template<class _CharT, class _Traits, class _Allocator>
|
|||
basic_string<_CharT, _Traits, _Allocator>
|
||||
operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Allocator>& __rhs)
|
||||
{
|
||||
basic_string<_CharT, _Traits, _Allocator> __r(__rhs.get_allocator());
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = __rhs.size();
|
||||
using _String = basic_string<_CharT, _Traits, _Allocator>;
|
||||
_String __r(_String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
|
||||
typename _String::size_type __rhs_sz = __rhs.size();
|
||||
__r.__init(&__lhs, 1, 1 + __rhs_sz);
|
||||
__r.append(__rhs.data(), __rhs_sz);
|
||||
return __r;
|
||||
|
@ -4197,9 +4200,10 @@ inline
|
|||
basic_string<_CharT, _Traits, _Allocator>
|
||||
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs)
|
||||
{
|
||||
basic_string<_CharT, _Traits, _Allocator> __r(__lhs.get_allocator());
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = __lhs.size();
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = _Traits::length(__rhs);
|
||||
using _String = basic_string<_CharT, _Traits, _Allocator>;
|
||||
_String __r(_String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
|
||||
typename _String::size_type __lhs_sz = __lhs.size();
|
||||
typename _String::size_type __rhs_sz = _Traits::length(__rhs);
|
||||
__r.__init(__lhs.data(), __lhs_sz, __lhs_sz + __rhs_sz);
|
||||
__r.append(__rhs, __rhs_sz);
|
||||
return __r;
|
||||
|
@ -4209,8 +4213,9 @@ template<class _CharT, class _Traits, class _Allocator>
|
|||
basic_string<_CharT, _Traits, _Allocator>
|
||||
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs)
|
||||
{
|
||||
basic_string<_CharT, _Traits, _Allocator> __r(__lhs.get_allocator());
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = __lhs.size();
|
||||
using _String = basic_string<_CharT, _Traits, _Allocator>;
|
||||
_String __r(_String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
|
||||
typename _String::size_type __lhs_sz = __lhs.size();
|
||||
__r.__init(__lhs.data(), __lhs_sz, __lhs_sz + 1);
|
||||
__r.push_back(__rhs);
|
||||
return __r;
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// This test ensures that we properly propagate allocators, per https://wg21.link/p1165r1
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class T>
|
||||
class soccc_allocator {
|
||||
int* soccc_count;
|
||||
int self_soccc_count;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
constexpr explicit soccc_allocator(int* soccc_count_, int self_coccc_count_ = 0)
|
||||
: soccc_count(soccc_count_), self_soccc_count(self_coccc_count_) {}
|
||||
|
||||
template <class U>
|
||||
constexpr soccc_allocator(const soccc_allocator<U>& a) : soccc_count(a.soccc_count) {}
|
||||
|
||||
constexpr T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); }
|
||||
constexpr void deallocate(T* p, std::size_t s) { std::allocator<T>().deallocate(p, s); }
|
||||
|
||||
constexpr soccc_allocator select_on_container_copy_construction() const {
|
||||
*soccc_count += 1;
|
||||
return soccc_allocator(soccc_count, self_soccc_count + 1);
|
||||
}
|
||||
|
||||
constexpr auto get_soccc() { return soccc_count; }
|
||||
constexpr auto get_self_soccc() { return self_soccc_count; }
|
||||
|
||||
typedef std::true_type propagate_on_container_copy_assignment;
|
||||
typedef std::true_type propagate_on_container_move_assignment;
|
||||
typedef std::true_type propagate_on_container_swap;
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
bool test() {
|
||||
using S = std::basic_string<CharT, std::char_traits<CharT>, soccc_allocator<CharT>>;
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs + rhs;
|
||||
assert(r.get_allocator().get_soccc() == &soccc_lhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 1);
|
||||
assert(soccc_lhs == 1);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs + std::move(rhs);
|
||||
assert(r.get_allocator().get_soccc() == &soccc_rhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 0);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = std::move(lhs) + rhs;
|
||||
assert(r.get_allocator().get_soccc() == &soccc_lhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 0);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = std::move(lhs) + std::move(rhs);
|
||||
assert(r.get_allocator().get_soccc() == &soccc_lhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 0);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs + rhs.data();
|
||||
assert(r.get_allocator().get_soccc() == &soccc_lhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 1);
|
||||
assert(soccc_lhs == 1);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs + rhs[0];
|
||||
assert(r.get_allocator().get_soccc() == &soccc_lhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 1);
|
||||
assert(soccc_lhs == 1);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = std::move(lhs) + rhs.data();
|
||||
assert(r.get_allocator().get_soccc() == &soccc_lhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 0);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = std::move(lhs) + rhs[0];
|
||||
assert(r.get_allocator().get_soccc() == &soccc_lhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 0);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs.data() + rhs;
|
||||
assert(r.get_allocator().get_soccc() == &soccc_rhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 1);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 1);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs[0] + rhs;
|
||||
assert(r.get_allocator().get_soccc() == &soccc_rhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 1);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 1);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs.data() + std::move(rhs);
|
||||
assert(r.get_allocator().get_soccc() == &soccc_rhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 0);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
{
|
||||
int soccc_lhs = 0;
|
||||
int soccc_rhs = 0;
|
||||
S lhs(soccc_allocator<CharT>{&soccc_lhs});
|
||||
S rhs(soccc_allocator<CharT>{&soccc_rhs});
|
||||
auto r = lhs[0] + std::move(rhs);
|
||||
assert(r.get_allocator().get_soccc() == &soccc_rhs);
|
||||
assert(r.get_allocator().get_self_soccc() == 0);
|
||||
assert(soccc_lhs == 0);
|
||||
assert(soccc_rhs == 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<char>();
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>();
|
||||
#endif
|
||||
#if TEST_STD_VER > 17
|
||||
// static_assert(test<char>());
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
// static_assert(test<wchar_t>());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue