1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10 
11 // <sstream>
12 
13 // template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
14 // class basic_stringstream
15 
16 // template<class T>
17 //   basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a);
18 
19 #include <cassert>
20 #include <concepts>
21 #include <memory>
22 #include <sstream>
23 #include <string>
24 #include <string_view>
25 
26 #include "constexpr_char_traits.h"
27 #include "nasty_string.h"
28 #include "test_allocator.h"
29 #include "test_convertible.h"
30 #include "test_macros.h"
31 
32 #include "../../helper_string_macros.h"
33 #include "../../helper_types.h"
34 
35 template <typename AllocT = std::allocator<nasty_char>>
test_sfinae_with_nasty_char()36 void test_sfinae_with_nasty_char() {
37   // nasty_char*
38   using NStrStream = std::basic_stringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
39 
40   static_assert(std::constructible_from<NStrStream, nasty_char*, test_allocator<nasty_char>>);
41   static_assert(test_convertible<NStrStream, nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
42 
43   // const nasty_char*
44   static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
45   static_assert(
46       test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
47 }
48 
49 template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
test_sfinae()50 void test_sfinae() {
51   using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
52 
53   // `CharT*`
54   static_assert(std::constructible_from<StrStream, CharT*, AllocT>);
55   static_assert(test_convertible<StrStream, CharT*, std::ios_base::openmode, const AllocT>());
56 
57   // `const CharT*`
58   static_assert(std::constructible_from<StrStream, const CharT*, AllocT>);
59   static_assert(test_convertible<StrStream, const CharT*, std::ios_base::openmode, const AllocT>());
60 
61   // `std::basic_string_view<CharT>`
62   static_assert(std::constructible_from<StrStream,
63                                         const std::basic_string_view<CharT, TraitsT>,
64                                         std::ios_base::openmode,
65                                         const AllocT>);
66   static_assert(test_convertible<StrStream,
67                                  const std::basic_string_view<CharT, TraitsT>,
68                                  std::ios_base::openmode,
69                                  const AllocT>());
70 
71   // `std::basic_string<CharT>`
72   static_assert(std::constructible_from<StrStream,
73                                         const std::basic_string<CharT, TraitsT>,
74                                         std::ios_base::openmode,
75                                         const AllocT>);
76   static_assert(
77       test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
78 
79   // ConstConvertibleStringView<CharT>
80   static_assert(std::constructible_from<StrStream,
81                                         const ConstConvertibleStringView<CharT, TraitsT>,
82                                         std::ios_base::openmode,
83                                         const AllocT>);
84   static_assert(test_convertible<StrStream,
85                                  const ConstConvertibleStringView<CharT, TraitsT>,
86                                  std::ios_base::openmode,
87                                  const AllocT>());
88 
89   // NonConstConvertibleStringView<CharT>
90   static_assert(!std::constructible_from<StrStream,
91                                          NonConstConvertibleStringView<CharT, TraitsT>,
92                                          std::ios_base::openmode,
93                                          const AllocT>);
94   static_assert(!test_convertible<StrStream,
95                                   NonConstConvertibleStringView<CharT, TraitsT>,
96                                   std::ios_base::openmode,
97                                   const AllocT>());
98 
99   static_assert(!std::constructible_from<StrStream,
100                                          const NonConstConvertibleStringView<CharT, TraitsT>,
101                                          std::ios_base::openmode,
102                                          const AllocT>);
103   static_assert(!test_convertible<StrStream,
104                                   const NonConstConvertibleStringView<CharT, TraitsT>,
105                                   std::ios_base::openmode,
106                                   const AllocT>());
107 
108   // Non-`string-view-like`
109   static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>);
110   static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode, const AllocT>());
111 
112   static_assert(!std::constructible_from<StrStream, const int, std::ios_base::openmode, const AllocT>);
113   static_assert(!test_convertible<StrStream, const int, std::ios_base::openmode, const AllocT>());
114 
115   // Non-mode
116   static_assert(
117       !std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>);
118   static_assert(
119       !test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>());
120 
121   // Non-allocator
122   static_assert(!std::constructible_from<StrStream,
123                                          const std::basic_string_view<CharT, TraitsT>,
124                                          std::ios_base::openmode,
125                                          const NonAllocator>);
126   static_assert(!test_convertible<StrStream,
127                                   const std::basic_string_view<CharT, TraitsT>,
128                                   std::ios_base::openmode,
129                                   const NonAllocator>());
130 }
131 
132 template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
test()133 void test() {
134   using StrStream = std::basic_stringstream<CharT, TraitsT, AllocT>;
135 
136   const AllocT allocator;
137 
138   // const CharT*
139   {
140     StrStream ss(CS("zmt"), std::ios_base::out | std::ios_base::in, allocator);
141     assert(ss.str() == CS("zmt"));
142     assert(ss.rdbuf()->get_allocator() == allocator);
143   }
144   // std::basic_string_view<CharT>
145   {
146     const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
147     StrStream ss(csv, std::ios_base::out | std::ios_base::in, allocator);
148     assert(ss.str() == CS("zmt"));
149     assert(ss.rdbuf()->get_allocator() == allocator);
150   }
151   // std::basic_string<CharT>
152   {
153     const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
154     StrStream ss(cs, std::ios_base::out | std::ios_base::in, allocator);
155     assert(ss.str() == CS("zmt"));
156     assert(ss.rdbuf()->get_allocator() == allocator);
157   }
158   // ConstConvertibleStringView<CharT>
159   {
160     const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
161     StrStream ss(sv, std::ios_base::out | std::ios_base::in, allocator);
162     assert(ss.str() == CS("zmt"));
163     assert(ss.rdbuf()->get_allocator() == allocator);
164   }
165 }
166 
main(int,char **)167 int main(int, char**) {
168   test_sfinae_with_nasty_char();
169   test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
170   test_sfinae<char>();
171   test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
172   test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
173   test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
174   test<char>();
175   test<char, constexpr_char_traits<char>, std::allocator<char>>();
176   test<char, std::char_traits<char>, test_allocator<char>>();
177   test<char, constexpr_char_traits<char>, test_allocator<char>>();
178 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
179   test_sfinae<wchar_t>();
180   test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
181   test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
182   test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
183   test<wchar_t>();
184   test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
185   test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
186   test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
187 #endif
188   return 0;
189 }
190