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

source code of libcxx/test/std/utilities/format/format.functions/P2418.pass.cpp