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 10 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME 11 12 // TODO FMT This test should not require std::to_chars(floating-point) 13 // XFAIL: availability-fp_to_chars-missing 14 15 // Tests whether a move only type can be formatted. This is required by 16 // P2418R2 "Add support for std::generator-like types to std::format" 17 18 // <format> 19 20 #include <format> 21 #include <cassert> 22 23 #include "MoveOnly.h" 24 #include "make_string.h" 25 #include "test_macros.h" 26 27 #ifndef TEST_HAS_NO_LOCALIZATION 28 # include <locale> 29 #endif 30 31 #define SV(S) MAKE_STRING_VIEW(CharT, S) 32 33 template <class CharT> 34 struct std::formatter<MoveOnly, CharT> : std::formatter<int, CharT> { 35 auto format(const MoveOnly& m, auto& ctx) const -> decltype(ctx.out()) { 36 return std::formatter<int, CharT>::format(m.get(), ctx); 37 } 38 }; 39 40 template <class CharT> 41 static void test() { 42 MoveOnly m{10}; 43 CharT buffer[10]; 44 #ifndef TEST_HAS_NO_LOCALIZATION 45 std::locale loc; 46 #endif 47 48 assert(std::format(SV("{}"), MoveOnly{}) == SV("1")); 49 50 assert(std::format(SV("{}"), m) == SV("10")); 51 assert(m.get() == 10); 52 53 assert(std::format(SV("{}"), std::move(m)) == SV("10")); 54 assert(m.get() == 10); 55 56 #ifndef TEST_HAS_NO_LOCALIZATION 57 assert(std::format(loc, SV("{}"), MoveOnly{}) == SV("1")); 58 59 assert(std::format(loc, SV("{}"), m) == SV("10")); 60 assert(m.get() == 10); 61 62 assert(std::format(loc, SV("{}"), std::move(m)) == SV("10")); 63 assert(m.get() == 10); 64 #endif 65 66 assert(std::format_to(buffer, SV("{}"), MoveOnly{}) == &buffer[1]); 67 68 assert(std::format_to(buffer, SV("{}"), m) == &buffer[2]); 69 assert(m.get() == 10); 70 71 assert(std::format_to(buffer, SV("{}"), std::move(m)) == &buffer[2]); 72 assert(m.get() == 10); 73 74 #ifndef TEST_HAS_NO_LOCALIZATION 75 assert(std::format_to(buffer, loc, SV("{}"), MoveOnly{}) == &buffer[1]); 76 77 assert(std::format_to(buffer, loc, SV("{}"), m) == &buffer[2]); 78 assert(m.get() == 10); 79 80 assert(std::format_to(buffer, loc, SV("{}"), std::move(m)) == &buffer[2]); 81 assert(m.get() == 10); 82 #endif 83 84 assert(std::format_to_n(buffer, 5, SV("{}"), MoveOnly{}).out == &buffer[1]); 85 86 assert(std::format_to_n(buffer, 5, SV("{}"), m).out == &buffer[2]); 87 assert(m.get() == 10); 88 89 assert(std::format_to_n(buffer, 5, SV("{}"), std::move(m)).out == &buffer[2]); 90 assert(m.get() == 10); 91 92 #ifndef TEST_HAS_NO_LOCALIZATION 93 assert(std::format_to_n(buffer, 5, loc, SV("{}"), MoveOnly{}).out == &buffer[1]); 94 95 assert(std::format_to_n(buffer, 5, loc, SV("{}"), m).out == &buffer[2]); 96 assert(m.get() == 10); 97 98 assert(std::format_to_n(buffer, 5, loc, SV("{}"), std::move(m)).out == &buffer[2]); 99 assert(m.get() == 10); 100 #endif 101 102 assert(std::formatted_size(SV("{}"), MoveOnly{}) == 1); 103 104 assert(std::formatted_size(SV("{}"), m) == 2); 105 assert(m.get() == 10); 106 107 assert(std::formatted_size(SV("{}"), std::move(m)) == 2); 108 assert(m.get() == 10); 109 110 #ifndef TEST_HAS_NO_LOCALIZATION 111 assert(std::formatted_size(loc, SV("{}"), MoveOnly{}) == 1); 112 113 assert(std::formatted_size(loc, SV("{}"), m) == 2); 114 assert(m.get() == 10); 115 116 assert(std::formatted_size(loc, SV("{}"), std::move(m)) == 2); 117 assert(m.get() == 10); 118 #endif 119 } 120 121 int main(int, char**) { 122 test<char>(); 123 124 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 125 test<wchar_t>(); 126 #endif 127 128 return 0; 129 } 130