mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-04 09:14:04 +08:00
Make allocator propagation more consistent for operator+(basic_string) (P1165R1)
2019-05-01 Nina Dinka Ranns <dinka.ranns@gmail.com> Make allocator propagation more consistent for operator+(basic_string) (P1165R1) * include/bits/basic_string.h (operator+(basic_string&&, basic_string&&): Changed resulting allocator to always be the one from the first parameter. * include/bits/basic_string.tcc (operator+(const _CharT*, const basic_string&)): Changed resulting allocator to be SOCCC on the second parameter's allocator. (operator+(_CharT, const basic_string&)): Likewise. * testsuite/21_strings/basic_string/allocator/char/operator_plus.cc: New. * testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc: New. From-SVN: r270953
This commit is contained in:
parent
2313938e75
commit
f4e678ef74
@ -1,3 +1,19 @@
|
||||
2019-05-01 Nina Dinka Ranns <dinka.ranns@gmail.com>
|
||||
|
||||
Make allocator propagation more consistent for
|
||||
operator+(basic_string) (P1165R1)
|
||||
* include/bits/basic_string.h
|
||||
(operator+(basic_string&&, basic_string&&): Changed resulting
|
||||
allocator to always be the one from the first parameter.
|
||||
* include/bits/basic_string.tcc
|
||||
(operator+(const _CharT*, const basic_string&)): Changed
|
||||
resulting allocator to be SOCCC on the second parameter's allocator.
|
||||
(operator+(_CharT, const basic_string&)): Likewise.
|
||||
* testsuite/21_strings/basic_string/allocator/char/operator_plus.cc:
|
||||
New.
|
||||
* testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc:
|
||||
New.
|
||||
|
||||
2019-05-07 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/regex.h: Improve docs.
|
||||
|
@ -6096,11 +6096,21 @@ _GLIBCXX_END_NAMESPACE_CXX11
|
||||
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
|
||||
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
|
||||
{
|
||||
const auto __size = __lhs.size() + __rhs.size();
|
||||
const bool __cond = (__size > __lhs.capacity()
|
||||
&& __size <= __rhs.capacity());
|
||||
return __cond ? std::move(__rhs.insert(0, __lhs))
|
||||
: std::move(__lhs.append(__rhs));
|
||||
#if _GLIBCXX_USE_CXX11_ABI
|
||||
using _Alloc_traits = allocator_traits<_Alloc>;
|
||||
bool __use_rhs = false;
|
||||
if _GLIBCXX17_CONSTEXPR (typename _Alloc_traits::is_always_equal{})
|
||||
__use_rhs = true;
|
||||
else if (__lhs.get_allocator() == __rhs.get_allocator())
|
||||
__use_rhs = true;
|
||||
if (__use_rhs)
|
||||
#endif
|
||||
{
|
||||
const auto __size = __lhs.size() + __rhs.size();
|
||||
if (__size > __lhs.capacity() && __size <= __rhs.capacity())
|
||||
return std::move(__rhs.insert(0, __lhs));
|
||||
}
|
||||
return std::move(__lhs.append(__rhs));
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
|
@ -1161,8 +1161,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
__glibcxx_requires_string(__lhs);
|
||||
typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
|
||||
typedef typename __string_type::size_type __size_type;
|
||||
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
|
||||
rebind<_CharT>::other _Char_alloc_type;
|
||||
typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits;
|
||||
const __size_type __len = _Traits::length(__lhs);
|
||||
__string_type __str;
|
||||
__string_type __str(_Alloc_traits::_S_select_on_copy(
|
||||
__rhs.get_allocator()));
|
||||
__str.reserve(__len + __rhs.size());
|
||||
__str.append(__lhs, __len);
|
||||
__str.append(__rhs);
|
||||
@ -1175,7 +1179,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{
|
||||
typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
|
||||
typedef typename __string_type::size_type __size_type;
|
||||
__string_type __str;
|
||||
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
|
||||
rebind<_CharT>::other _Char_alloc_type;
|
||||
typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits;
|
||||
__string_type __str(_Alloc_traits::_S_select_on_copy(
|
||||
__rhs.get_allocator()));
|
||||
const __size_type __len = __rhs.size();
|
||||
__str.reserve(__len + 1);
|
||||
__str.append(__size_type(1), __lhs);
|
||||
|
@ -0,0 +1,151 @@
|
||||
// 2019-04-30 Nina Dinka Ranns <dinka.ranns@gmail.com>
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-do run { target c++11 } }
|
||||
// COW strings don't support C++11 allocators:
|
||||
// { dg-require-effective-target cxx11-abi }
|
||||
|
||||
#include <string>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_allocator.h>
|
||||
#include <ext/throw_allocator.h>
|
||||
|
||||
using C = char;
|
||||
using traits = std::char_traits<C>;
|
||||
|
||||
using __gnu_test::propagating_allocator;
|
||||
|
||||
void test01()
|
||||
{
|
||||
typedef propagating_allocator<C, true> alloc_type;
|
||||
typedef std::basic_string<C, traits, alloc_type> test_type;
|
||||
|
||||
test_type v1("something",alloc_type(1));
|
||||
test_type v2("something",alloc_type(2));
|
||||
auto r1 = v1 + v2;
|
||||
VERIFY(r1.get_allocator().get_personality() == 1);
|
||||
|
||||
auto r2 = v1 + std::move(v2);
|
||||
VERIFY(r2.get_allocator().get_personality() == 2);
|
||||
|
||||
test_type v3("something", alloc_type(3));
|
||||
test_type v4("something", alloc_type(4));
|
||||
auto r3 = std::move(v3) + v4;
|
||||
VERIFY(r3.get_allocator().get_personality() == 3);
|
||||
|
||||
auto r4 = std::move(v1) +std::move(v4);
|
||||
VERIFY(r4.get_allocator().get_personality() == 1);
|
||||
|
||||
test_type v5("something", alloc_type(5));
|
||||
auto r5 = v5 + "str";
|
||||
VERIFY(r5.get_allocator().get_personality() == 5);
|
||||
|
||||
auto r6 = v5 + 'c';
|
||||
VERIFY(r6.get_allocator().get_personality() == 5);
|
||||
|
||||
auto r7 = std::move(v5) + "str";
|
||||
VERIFY(r7.get_allocator().get_personality() == 5);
|
||||
|
||||
test_type v6("something", alloc_type(6));
|
||||
auto r8 = std::move(v6) + 'c';
|
||||
VERIFY(r8.get_allocator().get_personality() == 6);
|
||||
|
||||
test_type v7("something", alloc_type(7));
|
||||
auto r9 = "str" + v7;
|
||||
VERIFY(r9.get_allocator().get_personality() == 7);
|
||||
|
||||
auto r10 = 'c' + v7;
|
||||
VERIFY(r10.get_allocator().get_personality() == 7);
|
||||
|
||||
auto r11 = "str" + std::move(v7);
|
||||
VERIFY(r11.get_allocator().get_personality() == 7);
|
||||
|
||||
test_type v8("something", alloc_type(8));
|
||||
auto r12 = 'c' + std::move(v8);
|
||||
VERIFY(r12.get_allocator().get_personality() == 8);
|
||||
}
|
||||
void test02()
|
||||
{
|
||||
typedef propagating_allocator<C, false> alloc_type;
|
||||
typedef std::basic_string<C, traits, alloc_type> test_type;
|
||||
|
||||
test_type v1("something",alloc_type(1));
|
||||
test_type v2("something",alloc_type(2));
|
||||
auto r1 = v1 + v2;
|
||||
VERIFY(r1.get_allocator().get_personality() != 1);
|
||||
|
||||
auto r2 = v1 + std::move(v2);
|
||||
VERIFY(r2.get_allocator().get_personality() == 2);
|
||||
|
||||
test_type v3("something", alloc_type(3));
|
||||
test_type v4("something", alloc_type(4));
|
||||
auto r3 = std::move(v3) + v4;
|
||||
VERIFY(r3.get_allocator().get_personality() == 3);
|
||||
|
||||
auto r4 = std::move(v1) +std::move(v4);
|
||||
VERIFY(r4.get_allocator().get_personality() == 1);
|
||||
|
||||
test_type v5("something", alloc_type(5));
|
||||
auto r5 = v5 + "str";
|
||||
VERIFY(r5.get_allocator().get_personality() != 5);
|
||||
|
||||
auto r6 = v5 + 'c';
|
||||
VERIFY(r6.get_allocator().get_personality() != 5);
|
||||
|
||||
auto r7 = std::move(v5) + "str";
|
||||
VERIFY(r7.get_allocator().get_personality() == 5);
|
||||
|
||||
test_type v6("something", alloc_type(6));
|
||||
auto r8 = std::move(v6) + 'c';
|
||||
VERIFY(r8.get_allocator().get_personality() == 6);
|
||||
|
||||
test_type v7("something", alloc_type(7));
|
||||
auto r9 = "str" + v7;
|
||||
VERIFY(r9.get_allocator().get_personality() != 7);
|
||||
|
||||
auto r10 = 'c' + v7;
|
||||
VERIFY(r10.get_allocator().get_personality() != 7);
|
||||
|
||||
auto r11 = "str" + std::move(v7);
|
||||
VERIFY(r11.get_allocator().get_personality() == 7);
|
||||
|
||||
test_type v8("something", alloc_type(8));
|
||||
auto r12 = 'c' + std::move(v8);
|
||||
VERIFY(r12.get_allocator().get_personality() == 8);
|
||||
}
|
||||
void test03()
|
||||
{
|
||||
typedef propagating_allocator<C, false> alloc_type;
|
||||
typedef std::basic_string<C, traits, alloc_type> test_type;
|
||||
|
||||
test_type v1("s",alloc_type(1));
|
||||
v1.resize(10);
|
||||
v1.shrink_to_fit();
|
||||
test_type v2(10000,'x',alloc_type(2));
|
||||
v2.reserve(10010);
|
||||
|
||||
auto r=std::move(v1)+std::move(v2);
|
||||
VERIFY(r.get_allocator().get_personality() == 1);
|
||||
}
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
// 2019-04-30 Nina Dinka Ranns <dinka.ranns@gmail.com>
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-do run { target c++11 } }
|
||||
// COW strings don't support C++11 allocators:
|
||||
// { dg-require-effective-target cxx11-abi }
|
||||
|
||||
#include <string>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_allocator.h>
|
||||
#include <ext/throw_allocator.h>
|
||||
|
||||
using C = wchar_t;
|
||||
using traits = std::char_traits<C>;
|
||||
|
||||
using __gnu_test::propagating_allocator;
|
||||
|
||||
void test01()
|
||||
{
|
||||
typedef propagating_allocator<C, true> alloc_type;
|
||||
typedef std::basic_string<C, traits, alloc_type> test_type;
|
||||
|
||||
test_type v1(L"something",alloc_type(1));
|
||||
test_type v2(L"something",alloc_type(2));
|
||||
auto r1 = v1 + v2;
|
||||
VERIFY(r1.get_allocator().get_personality() == 1);
|
||||
|
||||
auto r2 = v1 + std::move(v2);
|
||||
VERIFY(r2.get_allocator().get_personality() == 2);
|
||||
|
||||
test_type v3(L"something", alloc_type(3));
|
||||
test_type v4(L"something", alloc_type(4));
|
||||
auto r3 = std::move(v3) + v4;
|
||||
VERIFY(r3.get_allocator().get_personality() == 3);
|
||||
|
||||
auto r4 = std::move(v1) +std::move(v4);
|
||||
VERIFY(r4.get_allocator().get_personality() == 1);
|
||||
|
||||
test_type v5(L"something", alloc_type(5));
|
||||
auto r5 = v5 + L"str";
|
||||
VERIFY(r5.get_allocator().get_personality() == 5);
|
||||
|
||||
auto r6 = v5 + L'c';
|
||||
VERIFY(r6.get_allocator().get_personality() == 5);
|
||||
|
||||
auto r7 = std::move(v5) + L"str";
|
||||
VERIFY(r7.get_allocator().get_personality() == 5);
|
||||
|
||||
test_type v6(L"something", alloc_type(6));
|
||||
auto r8 = std::move(v6) + L'c';
|
||||
VERIFY(r8.get_allocator().get_personality() == 6);
|
||||
|
||||
test_type v7(L"something", alloc_type(7));
|
||||
auto r9 = L"str" + v7;
|
||||
VERIFY(r9.get_allocator().get_personality() == 7);
|
||||
|
||||
auto r10 = L'c' + v7;
|
||||
VERIFY(r10.get_allocator().get_personality() == 7);
|
||||
|
||||
auto r11 = L"str" + std::move(v7);
|
||||
VERIFY(r11.get_allocator().get_personality() == 7);
|
||||
|
||||
test_type v8(L"something", alloc_type(8));
|
||||
auto r12 = L'c' + std::move(v8);
|
||||
VERIFY(r12.get_allocator().get_personality() == 8);
|
||||
}
|
||||
|
||||
void test02()
|
||||
{
|
||||
typedef propagating_allocator<C, false> alloc_type;
|
||||
typedef std::basic_string<C, traits, alloc_type> test_type;
|
||||
|
||||
test_type v1(L"something",alloc_type(1));
|
||||
test_type v2(L"something",alloc_type(2));
|
||||
auto r1 = v1 + v2;
|
||||
VERIFY(r1.get_allocator().get_personality() != 1);
|
||||
|
||||
auto r2 = v1 + std::move(v2);
|
||||
VERIFY(r2.get_allocator().get_personality() == 2);
|
||||
|
||||
test_type v3(L"something", alloc_type(3));
|
||||
test_type v4(L"something", alloc_type(4));
|
||||
auto r3 = std::move(v3) + v4;
|
||||
VERIFY(r3.get_allocator().get_personality() == 3);
|
||||
|
||||
auto r4 = std::move(v1) +std::move(v4);
|
||||
VERIFY(r4.get_allocator().get_personality() == 1);
|
||||
|
||||
test_type v5(L"something", alloc_type(5));
|
||||
auto r5 = v5 + L"str";
|
||||
VERIFY(r5.get_allocator().get_personality() != 5);
|
||||
|
||||
auto r6 = v5 + L'c';
|
||||
VERIFY(r6.get_allocator().get_personality() != 5);
|
||||
|
||||
auto r7 = std::move(v5) + L"str";
|
||||
VERIFY(r7.get_allocator().get_personality() == 5);
|
||||
|
||||
test_type v6(L"something", alloc_type(6));
|
||||
auto r8 = std::move(v6) + L'c';
|
||||
VERIFY(r8.get_allocator().get_personality() == 6);
|
||||
|
||||
test_type v7(L"something", alloc_type(7));
|
||||
auto r9 = L"str" + v7;
|
||||
VERIFY(r9.get_allocator().get_personality() != 7);
|
||||
|
||||
auto r10 = L'c' + v7;
|
||||
VERIFY(r10.get_allocator().get_personality() != 7);
|
||||
|
||||
auto r11 = L"str" + std::move(v7);
|
||||
VERIFY(r11.get_allocator().get_personality() == 7);
|
||||
|
||||
test_type v8(L"something", alloc_type(8));
|
||||
auto r12 = L'c' + std::move(v8);
|
||||
VERIFY(r12.get_allocator().get_personality() == 8);
|
||||
}
|
||||
void test03()
|
||||
{
|
||||
typedef propagating_allocator<C, false> alloc_type;
|
||||
typedef std::basic_string<C, traits, alloc_type> test_type;
|
||||
|
||||
test_type v1(L"s",alloc_type(1));
|
||||
v1.resize(10);
|
||||
v1.shrink_to_fit();
|
||||
test_type v2(10000,L'x',alloc_type(2));
|
||||
v2.reserve(10010);
|
||||
|
||||
auto r=std::move(v1)+std::move(v2);
|
||||
VERIFY(r.get_allocator().get_personality() == 1);
|
||||
}
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user