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, c++20 |
9 | |
10 | // This test uses std::filesystem::path, which is not always available |
11 | // XFAIL: availability-filesystem-missing |
12 | |
13 | // <format> |
14 | |
15 | // template<ranges::input_range R> |
16 | // requires same_as<R, remove_cvref_t<R>> |
17 | // constexpr range_format format_kind<R> = see below; |
18 | |
19 | #include <format> |
20 | |
21 | #include <array> |
22 | #include <deque> |
23 | #include <filesystem> |
24 | #include <format> |
25 | #include <forward_list> |
26 | #include <iterator> |
27 | #include <list> |
28 | #include <map> |
29 | #include <ranges> |
30 | #include <set> |
31 | #include <span> |
32 | #include <unordered_map> |
33 | #include <unordered_set> |
34 | #include <valarray> |
35 | #include <vector> |
36 | |
37 | #include "test_macros.h" |
38 | |
39 | // [format.range.fmtkind] |
40 | // If same_as<remove_cvref_t<ranges::range_reference_t<R>>, R> is true, |
41 | // format_kind<R> is range_format::disabled. |
42 | // [Note 1: This prevents constraint recursion for ranges whose reference type |
43 | // is the same range type. For example, std::filesystem::path is a range of |
44 | // std::filesystem::path. - end note] |
45 | struct recursive_range { |
46 | struct iterator { |
47 | using iterator_concept = std::input_iterator_tag; |
48 | using value_type = recursive_range; |
49 | using difference_type = std::ptrdiff_t; |
50 | using reference = recursive_range; |
51 | |
52 | reference operator*() const; |
53 | |
54 | iterator& operator++(); |
55 | iterator operator++(int); |
56 | |
57 | friend bool operator==(const iterator&, const iterator&); |
58 | }; |
59 | |
60 | iterator begin(); |
61 | iterator end(); |
62 | }; |
63 | |
64 | static_assert(std::ranges::input_range<recursive_range>, "format_kind requires an input range" ); |
65 | static_assert(std::format_kind<recursive_range> == std::range_format::disabled); |
66 | |
67 | static_assert(std::format_kind<std::filesystem::path> == std::range_format::disabled); |
68 | |
69 | static_assert(std::format_kind<std::map<int, int>> == std::range_format::map); |
70 | static_assert(std::format_kind<std::multimap<int, int>> == std::range_format::map); |
71 | static_assert(std::format_kind<std::unordered_map<int, int>> == std::range_format::map); |
72 | static_assert(std::format_kind<std::unordered_multimap<int, int>> == std::range_format::map); |
73 | |
74 | static_assert(std::format_kind<std::set<int>> == std::range_format::set); |
75 | static_assert(std::format_kind<std::multiset<int>> == std::range_format::set); |
76 | static_assert(std::format_kind<std::unordered_set<int>> == std::range_format::set); |
77 | static_assert(std::format_kind<std::unordered_multiset<int>> == std::range_format::set); |
78 | |
79 | static_assert(std::format_kind<std::array<int, 1>> == std::range_format::sequence); |
80 | static_assert(std::format_kind<std::vector<int>> == std::range_format::sequence); |
81 | static_assert(std::format_kind<std::deque<int>> == std::range_format::sequence); |
82 | static_assert(std::format_kind<std::forward_list<int>> == std::range_format::sequence); |
83 | static_assert(std::format_kind<std::list<int>> == std::range_format::sequence); |
84 | |
85 | static_assert(std::format_kind<std::span<int>> == std::range_format::sequence); |
86 | |
87 | static_assert(std::format_kind<std::valarray<int>> == std::range_format::sequence); |
88 | |
89 | // [format.range.fmtkind]/3 |
90 | // Remarks: Pursuant to [namespace.std], users may specialize format_kind for |
91 | // cv-unqualified program-defined types that model ranges::input_range. Such |
92 | // specializations shall be usable in constant expressions ([expr.const]) and |
93 | // have type const range_format. |
94 | // Note only test the specializing, not all constraints. |
95 | struct no_specialization : std::ranges::view_base { |
96 | using key_type = void; |
97 | int* begin() const; |
98 | int* end() const; |
99 | }; |
100 | static_assert(std::format_kind<no_specialization> == std::range_format::set); |
101 | |
102 | // The struct's "contents" are the same as no_specialization. |
103 | struct specialized : std::ranges::view_base { |
104 | using key_type = void; |
105 | int* begin() const; |
106 | int* end() const; |
107 | }; |
108 | |
109 | template <> |
110 | constexpr std::range_format std::format_kind<specialized> = std::range_format::sequence; |
111 | static_assert(std::format_kind<specialized> == std::range_format::sequence); |
112 | |