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