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_ostringstream
15 
16 // template<class T>
17 //   explicit basic_ostringstream(const T& t, ios_base::openmode which);
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_ostringstream<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>());
42 
43   // const nasty_char*
44   using NStrStream = std::basic_ostringstream<nasty_char, nasty_char_traits, test_allocator<nasty_char>>;
45 
46   static_assert(std::constructible_from<NStrStream, const nasty_char*, test_allocator<nasty_char>>);
47   static_assert(!test_convertible<NStrStream, const nasty_char*, std::ios_base::openmode>());
48 }
49 
50 template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
test_sfinae()51 void test_sfinae() {
52   using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
53 
54   // `CharT*`
55   static_assert(std::constructible_from<StrStream, CharT*, std::ios_base::openmode>);
56   static_assert(!test_convertible<StrStream, CharT*, std::ios_base::openmode>());
57 
58   // `const CharT*`
59   static_assert(std::constructible_from<StrStream, const CharT*, std::ios_base::openmode>);
60   static_assert(!test_convertible<StrStream, const CharT*, std::ios_base::openmode>());
61 
62   // `std::basic_string_view<CharT>`
63   static_assert(
64       std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>);
65   static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, std::ios_base::openmode>());
66 
67   // `std::basic_string<CharT>`
68   static_assert(std::constructible_from<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>);
69   static_assert(!test_convertible<StrStream, const std::basic_string<CharT, TraitsT>, std::ios_base::openmode>());
70 
71   // ConstConvertibleStringView<CharT>
72   static_assert(
73       std::constructible_from<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
74   static_assert(
75       !test_convertible<StrStream, const ConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
76 
77   // NonConstConvertibleStringView<CharT>
78   static_assert(
79       !std::constructible_from<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
80   static_assert(!test_convertible<StrStream, NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
81 
82   static_assert(
83       !std::
84           constructible_from<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>);
85   static_assert(
86       !test_convertible<StrStream, const NonConstConvertibleStringView<CharT, TraitsT>, std::ios_base::openmode>());
87 
88   // Non-`string-view-like`
89   static_assert(!std::constructible_from<StrStream, const SomeObject, std::ios_base::openmode>);
90   static_assert(!test_convertible<StrStream, const SomeObject, std::ios_base::openmode>());
91 
92   // Non-mode
93   static_assert(!std::constructible_from<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>);
94   static_assert(!test_convertible<StrStream, const std::basic_string_view<CharT, TraitsT>, const SomeObject>());
95 }
96 
97 template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
test()98 void test() {
99   using StrStream = std::basic_ostringstream<CharT, TraitsT, AllocT>;
100 
101   const AllocT allocator;
102 
103   // const CharT*
104   {
105     StrStream ss(CS("zmt"), std::ios_base::binary);
106     assert(ss.str() == CS("zmt"));
107   }
108   // std::basic_string_view<CharT>
109   {
110     const std::basic_string_view<CharT, TraitsT> csv = SV("zmt");
111     StrStream ss(csv, std::ios_base::binary);
112     assert(ss.str() == CS("zmt"));
113   }
114   // std::basic_string<CharT>
115   {
116     const std::basic_string<CharT, TraitsT, AllocT> cs = ST("zmt", allocator);
117     StrStream ss(cs, std::ios_base::binary);
118     assert(ss.str() == CS("zmt"));
119   }
120   // ConstConvertibleStringView<CharT>
121   {
122     const ConstConvertibleStringView<CharT, TraitsT> sv{CS("zmt")};
123     StrStream ss(sv, std::ios_base::binary);
124     assert(ss.str() == CS("zmt"));
125   }
126 }
127 
main(int,char **)128 int main(int, char**) {
129   test_sfinae_with_nasty_char();
130   test_sfinae_with_nasty_char<test_allocator<nasty_char>>();
131   test_sfinae<char>();
132   test_sfinae<char, constexpr_char_traits<char>, std::allocator<char>>();
133   test_sfinae<char, std::char_traits<char>, test_allocator<char>>();
134   test_sfinae<char, constexpr_char_traits<char>, test_allocator<char>>();
135   test<char>();
136   test<char, constexpr_char_traits<char>, std::allocator<char>>();
137   test<char, std::char_traits<char>, test_allocator<char>>();
138   test<char, constexpr_char_traits<char>, test_allocator<char>>();
139 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
140   test_sfinae<wchar_t>();
141   test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
142   test_sfinae<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
143   test_sfinae<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
144   test<wchar_t>();
145   test<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>();
146   test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
147   test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
148 #endif
149   return 0;
150 }
151