1f7b43230SLouis Dionne //===----------------------------------------------------------------------===//
2f7b43230SLouis Dionne //
3f7b43230SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f7b43230SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
5f7b43230SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f7b43230SLouis Dionne //
7f7b43230SLouis Dionne //===----------------------------------------------------------------------===//
8f7b43230SLouis Dionne
9*ac8c9f1eSLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
10a7f9895cSLouis Dionne // UNSUPPORTED: no-localization
11c352fa74SLouis Dionne // UNSUPPORTED: availability-filesystem-missing
12f7b43230SLouis Dionne
13f7b43230SLouis Dionne // <filesystem>
14f7b43230SLouis Dionne
15f7b43230SLouis Dionne // class path
16f7b43230SLouis Dionne
17f7b43230SLouis Dionne // template <class charT, class traits>
18f7b43230SLouis Dionne // basic_ostream<charT, traits>&
19f7b43230SLouis Dionne // operator<<(basic_ostream<charT, traits>& os, const path& p);
20f7b43230SLouis Dionne //
21f7b43230SLouis Dionne // template <class charT, class traits>
22f7b43230SLouis Dionne // basic_istream<charT, traits>&
23f7b43230SLouis Dionne // operator>>(basic_istream<charT, traits>& is, path& p)
24f7b43230SLouis Dionne //
25f7b43230SLouis Dionne
26*ac8c9f1eSLouis Dionne #include <filesystem>
27f7b43230SLouis Dionne #include <type_traits>
28f7b43230SLouis Dionne #include <sstream>
29f7b43230SLouis Dionne #include <cassert>
30f7b43230SLouis Dionne #include <iostream>
31f7b43230SLouis Dionne
32cc89063bSNico Weber #include "count_new.h"
33c352fa74SLouis Dionne #include "make_string.h"
34c352fa74SLouis Dionne #include "test_iterators.h"
35c352fa74SLouis Dionne #include "test_macros.h"
36*ac8c9f1eSLouis Dionne namespace fs = std::filesystem;
37f7b43230SLouis Dionne
38f7b43230SLouis Dionne MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789");
39f7b43230SLouis Dionne MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\"");
40f7b43230SLouis Dionne
41f7b43230SLouis Dionne template <class CharT>
doIOTest()42f7b43230SLouis Dionne void doIOTest() {
43f7b43230SLouis Dionne using namespace fs;
44f7b43230SLouis Dionne using Ptr = const CharT*;
45f7b43230SLouis Dionne using StrStream = std::basic_stringstream<CharT>;
46f7b43230SLouis Dionne const Ptr E = OutStr;
47f7b43230SLouis Dionne const path p((const char*)InStr);
48f7b43230SLouis Dionne StrStream ss;
49f7b43230SLouis Dionne { // test output
50f7b43230SLouis Dionne auto& ret = (ss << p);
51f7b43230SLouis Dionne assert(ss.str() == E);
52f7b43230SLouis Dionne assert(&ret == &ss);
53f7b43230SLouis Dionne }
54f7b43230SLouis Dionne { // test input
55f7b43230SLouis Dionne path p_in;
56f7b43230SLouis Dionne auto& ret = ss >> p_in;
573784bdf2SMartin Storsjö assert(p_in.native() == (const path::value_type*)InStr);
58f7b43230SLouis Dionne assert(&ret == &ss);
59f7b43230SLouis Dionne }
60f7b43230SLouis Dionne }
61f7b43230SLouis Dionne
62f7b43230SLouis Dionne namespace impl {
63f7b43230SLouis Dionne using namespace fs;
64f7b43230SLouis Dionne
65f7b43230SLouis Dionne template <class Stream, class Tp, class = decltype(std::declval<Stream&>() << std::declval<Tp&>())>
66f7b43230SLouis Dionne std::true_type is_ostreamable_imp(int);
67f7b43230SLouis Dionne
68f7b43230SLouis Dionne template <class Stream, class Tp>
69f7b43230SLouis Dionne std::false_type is_ostreamable_imp(long);
70f7b43230SLouis Dionne
71f7b43230SLouis Dionne template <class Stream, class Tp, class = decltype(std::declval<Stream&>() >> std::declval<Tp&>())>
72f7b43230SLouis Dionne std::true_type is_istreamable_imp(int);
73f7b43230SLouis Dionne
74f7b43230SLouis Dionne template <class Stream, class Tp>
75f7b43230SLouis Dionne std::false_type is_istreamable_imp(long);
76f7b43230SLouis Dionne
77f7b43230SLouis Dionne
78f7b43230SLouis Dionne } // namespace impl
79f7b43230SLouis Dionne
80f7b43230SLouis Dionne template <class Stream, class Tp>
81f7b43230SLouis Dionne struct is_ostreamable : decltype(impl::is_ostreamable_imp<Stream, Tp>(0)) {};
82f7b43230SLouis Dionne template <class Stream, class Tp>
83f7b43230SLouis Dionne struct is_istreamable : decltype(impl::is_istreamable_imp<Stream, Tp>(0)) {};
84f7b43230SLouis Dionne
test_LWG2989()85f7b43230SLouis Dionne void test_LWG2989() {
86f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
87f7b43230SLouis Dionne static_assert(!is_ostreamable<decltype(std::cout), std::wstring>::value, "");
88f7b43230SLouis Dionne static_assert(!is_ostreamable<decltype(std::wcout), std::string>::value, "");
89f7b43230SLouis Dionne static_assert(!is_istreamable<decltype(std::cin), std::wstring>::value, "");
90f7b43230SLouis Dionne static_assert(!is_istreamable<decltype(std::wcin), std::string>::value, "");
91f4c1258dSLouis Dionne #endif
92f7b43230SLouis Dionne }
93f7b43230SLouis Dionne
main(int,char **)94f7b43230SLouis Dionne int main(int, char**) {
95f7b43230SLouis Dionne doIOTest<char>();
96f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
97f7b43230SLouis Dionne doIOTest<wchar_t>();
98f4c1258dSLouis Dionne #endif
99b6d87773SKonstantin Varlamov // TODO(var-const): uncomment when it becomes possible to instantiate a `basic_ostream` object with a sized character
100b6d87773SKonstantin Varlamov // type (see https://llvm.org/PR53119).
101f7b43230SLouis Dionne //doIOTest<char16_t>();
102f7b43230SLouis Dionne //doIOTest<char32_t>();
103f7b43230SLouis Dionne test_LWG2989();
104f7b43230SLouis Dionne
105f7b43230SLouis Dionne return 0;
106f7b43230SLouis Dionne }
107