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_stringbuf
15 
16 // template<class T>
17 //   basic_stringbuf(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 NStrBuf = std::basic_stringbuf<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
39 
40   static_assert(std::constructible_from<NStrBuf, nasty_char*, test_allocator<nasty_char>>);
41   static_assert(test_convertible<NStrBuf, nasty_char*, std::ios_base::openmode, const test_allocator<nasty_char>>());
42 
43   // const nasty_char*
44   static_assert(std::constructible_from<NStrBuf, const nasty_char*, test_allocator<nasty_char>>);
45   static_assert(
46       test_convertible<NStrBuf, 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 StrBuf = std::basic_stringbuf<CharT, TraitsT, AllocT>;
52 
53   // `CharT*`
54   static_assert(std::constructible_from<StrBuf, CharT*, AllocT>);
55   static_assert(test_convertible<StrBuf, CharT*, std::ios_base::openmode, const AllocT>());
56 
57   // `const CharT*`
58   static_assert(std::constructible_from<StrBuf, const CharT*, AllocT>);
59   static_assert(test_convertible<StrBuf, const CharT*, std::ios_base::openmode, const AllocT>());
60 
61   // `std::basic_string_view<CharT>`
62   static_assert(std::constructible_from<StrBuf,
63                                         const std::basic_string_view<CharT, TraitsT>,
64                                         std::ios_base::openmode,
65                                         const AllocT>);
66   static_assert(
67       test_convertible<StrBuf, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
68 
69   // `std::basic_string<CharT>`
70   static_assert(
71       std::constructible_from<StrBuf, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>);
72   static_assert(
73       test_convertible<StrBuf, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode, const AllocT>());
74 
75   // ConstConvertibleStringView<CharT>
76   static_assert(std::constructible_from<StrBuf,
77                                         const ConstConvertibleStringView<CharT, TraitsT>,
78                                         std::ios_base::openmode,
79                                         const AllocT>);
80   static_assert(test_convertible<StrBuf,
81                                  const ConstConvertibleStringView<CharT, TraitsT>,
82                                  std::ios_base::openmode,
83                                  const AllocT>());
84 
85   // NonConstConvertibleStringView<CharT>
86   static_assert(!std::constructible_from<StrBuf,
87                                          NonConstConvertibleStringView<CharT, TraitsT>,
88                                          std::ios_base::openmode,
89                                          const AllocT>);
90   static_assert(!test_convertible<StrBuf,
91                                   NonConstConvertibleStringView<CharT, TraitsT>,
92                                   std::ios_base::openmode,
93                                   const AllocT>());
94 
95   static_assert(!std::constructible_from<StrBuf,
96                                          const NonConstConvertibleStringView<CharT, TraitsT>,
97                                          std::ios_base::openmode,
98                                          const AllocT>);
99   static_assert(!test_convertible<StrBuf,
100                                   const NonConstConvertibleStringView<CharT, TraitsT>,
101                                   std::ios_base::openmode,
102                                   const AllocT>());
103 
104   // Non-`string-view-like`
105   static_assert(!std::constructible_from<StrBuf, const SomeObject, std::ios_base::openmode, const AllocT>);
106   static_assert(!test_convertible<StrBuf, const SomeObject, std::ios_base::openmode, const AllocT>());
107 
108   static_assert(!std::constructible_from<StrBuf, const int, std::ios_base::openmode, const AllocT>);
109   static_assert(!test_convertible<StrBuf, const int, std::ios_base::openmode, const AllocT>());
110 
111   // Non-mode
112   static_assert(
113       !std::constructible_from<StrBuf, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>);
114   static_assert(!test_convertible<StrBuf, const std::basic_string_view<CharT, TraitsT>, NonMode, const NonAllocator>());
115 
116   // Non-allocator
117   static_assert(!std::constructible_from<StrBuf,
118                                          const std::basic_string_view<CharT, TraitsT>,
119                                          std::ios_base::openmode,
120                                          const NonAllocator>);
121   static_assert(!test_convertible<StrBuf,
122                                   const std::basic_string_view<CharT, TraitsT>,
123                                   std::ios_base::openmode,
124                                   const NonAllocator>());
125 }
126 
127 template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
test()128 void test() {
129   using StrBuf = std::basic_stringbuf<CharT, TraitsT, AllocT>;
130 
131   const AllocT allocator;
132 
133   // const CharT*
134   {
135     StrBuf ss(CS("zmt"), std::ios_base::out | std::ios_base::in, allocator);
136     assert(ss.str() == CS("zmt"));
137     assert(ss.get_allocator() == allocator);
138   }
139   // std::basic_string_view<CharT>
140   {
141     const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
142     StrBuf ss(csv, std::ios_base::out | std::ios_base::in, allocator);
143     assert(ss.str() == CS("zmt"));
144     assert(ss.get_allocator() == allocator);
145   }
146   // std::basic_string<CharT>
147   {
148     const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
149     StrBuf ss(cs, std::ios_base::out | std::ios_base::in, allocator);
150     assert(ss.str() == CS("zmt"));
151     assert(ss.get_allocator() == allocator);
152   }
153   // ConstConvertibleStringView<CharT>
154   {
155     const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
156     StrBuf ss(sv, std::ios_base::out | std::ios_base::in, allocator);
157     assert(ss.str() == CS("zmt"));
158     assert(ss.get_allocator() == allocator);
159   }
160 }
161 
main(int,char **)162 int main(int, char**) {
163   test_sfinae_with_nasty_char();
164   test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
165   test_sfinae<char>();
166   test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
167   test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
168   test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
169   test<char>();
170   test<char, constexpr_char_traits<char>, std::allocator<char>>();
171   test<char, std::char_traits<char>, test_allocator<char>>();
172   test<char, constexpr_char_traits<char>, test_allocator<char>>();
173 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
174   test_sfinae<wchar_t>();
175   test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
176   test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
177   test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
178   test<wchar_t>();
179   test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
180   test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
181   test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
182 #endif
183   return 0;
184 }
185