1*7cc72a0aSMark de Wever //===----------------------------------------------------------------------===//
2*7cc72a0aSMark de Wever //
3*7cc72a0aSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*7cc72a0aSMark de Wever // See https://llvm.org/LICENSE.txt for license information.
5*7cc72a0aSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*7cc72a0aSMark de Wever //
7*7cc72a0aSMark de Wever //===----------------------------------------------------------------------===//
8*7cc72a0aSMark de Wever
9*7cc72a0aSMark de Wever // UNSUPPORTED: c++03, c++11, c++14, c++17
10*7cc72a0aSMark de Wever // UNSUPPORTED: no-localization
11*7cc72a0aSMark de Wever // UNSUPPORTED: libcpp-has-no-experimental-syncstream
12*7cc72a0aSMark de Wever
13*7cc72a0aSMark de Wever // <syncstream>
14*7cc72a0aSMark de Wever
15*7cc72a0aSMark de Wever // template <class charT, class traits, class Allocator>
16*7cc72a0aSMark de Wever // class basic_osyncstream;
17*7cc72a0aSMark de Wever
18*7cc72a0aSMark de Wever // basic_osyncstream& operator=(basic_osyncstream&& rhs);
19*7cc72a0aSMark de Wever
20*7cc72a0aSMark de Wever #include <syncstream>
21*7cc72a0aSMark de Wever #include <sstream>
22*7cc72a0aSMark de Wever #include <cassert>
23*7cc72a0aSMark de Wever
24*7cc72a0aSMark de Wever #include "test_macros.h"
25*7cc72a0aSMark de Wever #include "test_allocator.h"
26*7cc72a0aSMark de Wever
27*7cc72a0aSMark de Wever template <class CharT, bool propagate>
test()28*7cc72a0aSMark de Wever static void test() {
29*7cc72a0aSMark de Wever using Traits = std::char_traits<CharT>;
30*7cc72a0aSMark de Wever using Allocator = std::conditional_t<propagate, other_allocator<CharT>, test_allocator<CharT>>;
31*7cc72a0aSMark de Wever static_assert(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value == propagate);
32*7cc72a0aSMark de Wever
33*7cc72a0aSMark de Wever using OS = std::basic_osyncstream<CharT, Traits, Allocator>;
34*7cc72a0aSMark de Wever
35*7cc72a0aSMark de Wever std::basic_stringbuf<CharT, Traits, Allocator> base1;
36*7cc72a0aSMark de Wever std::basic_stringbuf<CharT, Traits, Allocator> base2;
37*7cc72a0aSMark de Wever
38*7cc72a0aSMark de Wever {
39*7cc72a0aSMark de Wever OS out1{&base1, Allocator{42}};
40*7cc72a0aSMark de Wever assert(out1.get_wrapped() == &base1);
41*7cc72a0aSMark de Wever
42*7cc72a0aSMark de Wever typename OS::syncbuf_type* sb1 = out1.rdbuf();
43*7cc72a0aSMark de Wever assert(sb1->get_wrapped() == &base1);
44*7cc72a0aSMark de Wever assert(sb1->get_allocator().get_data() == 42);
45*7cc72a0aSMark de Wever
46*7cc72a0aSMark de Wever out1 << CharT('A');
47*7cc72a0aSMark de Wever
48*7cc72a0aSMark de Wever static_assert(!noexcept(out1.operator=(std::move(out1)))); // LWG-3867
49*7cc72a0aSMark de Wever OS out2{&base2, Allocator{99}};
50*7cc72a0aSMark de Wever
51*7cc72a0aSMark de Wever out2 << CharT('Z');
52*7cc72a0aSMark de Wever
53*7cc72a0aSMark de Wever // Validate the data is still in the syncbuf and not in the stringbuf.
54*7cc72a0aSMark de Wever assert(base1.str().empty());
55*7cc72a0aSMark de Wever assert(base2.str().empty());
56*7cc72a0aSMark de Wever
57*7cc72a0aSMark de Wever out2 = std::move(out1);
58*7cc72a0aSMark de Wever
59*7cc72a0aSMark de Wever // Since sb2 is overwritten by the move its data should be in its stringbuf.
60*7cc72a0aSMark de Wever assert(base1.str().empty());
61*7cc72a0aSMark de Wever assert(base2.str().size() == 1);
62*7cc72a0aSMark de Wever assert(base2.str()[0] == CharT('Z'));
63*7cc72a0aSMark de Wever
64*7cc72a0aSMark de Wever assert(out2.get_wrapped() == &base1);
65*7cc72a0aSMark de Wever
66*7cc72a0aSMark de Wever typename OS::syncbuf_type* sb2 = out2.rdbuf();
67*7cc72a0aSMark de Wever assert(sb2->get_wrapped() == &base1);
68*7cc72a0aSMark de Wever if constexpr (std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value)
69*7cc72a0aSMark de Wever assert(sb2->get_allocator().get_data() == 42);
70*7cc72a0aSMark de Wever else
71*7cc72a0aSMark de Wever assert(sb2->get_allocator().get_data() == 99);
72*7cc72a0aSMark de Wever
73*7cc72a0aSMark de Wever assert(out1.get_wrapped() == nullptr);
74*7cc72a0aSMark de Wever assert(sb1->get_wrapped() == nullptr);
75*7cc72a0aSMark de Wever
76*7cc72a0aSMark de Wever // The data written to 2 will be stored in sb1. The write happens after the destruction.
77*7cc72a0aSMark de Wever out2 << CharT('B');
78*7cc72a0aSMark de Wever assert(base1.str().empty());
79*7cc72a0aSMark de Wever }
80*7cc72a0aSMark de Wever
81*7cc72a0aSMark de Wever assert(base1.str().size() == 2);
82*7cc72a0aSMark de Wever assert(base1.str()[0] == CharT('A'));
83*7cc72a0aSMark de Wever assert(base1.str()[1] == CharT('B'));
84*7cc72a0aSMark de Wever assert(base2.str().size() == 1);
85*7cc72a0aSMark de Wever assert(base2.str()[0] == CharT('Z'));
86*7cc72a0aSMark de Wever }
87*7cc72a0aSMark de Wever
88*7cc72a0aSMark de Wever template <class CharT>
test()89*7cc72a0aSMark de Wever static void test() {
90*7cc72a0aSMark de Wever test<CharT, true>();
91*7cc72a0aSMark de Wever test<CharT, false>();
92*7cc72a0aSMark de Wever }
93*7cc72a0aSMark de Wever
main(int,char **)94*7cc72a0aSMark de Wever int main(int, char**) {
95*7cc72a0aSMark de Wever test<char>();
96*7cc72a0aSMark de Wever #ifndef TEST_HAS_NO_WIDE_CHARACTERS
97*7cc72a0aSMark de Wever test<wchar_t>();
98*7cc72a0aSMark de Wever #endif
99*7cc72a0aSMark de Wever
100*7cc72a0aSMark de Wever return 0;
101*7cc72a0aSMark de Wever }
102