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

source code of libcxx/test/std/utilities/format/format.range/format.range.fmtkind/format_kind.compile.pass.cpp