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]
45struct 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
64static_assert(std::ranges::input_range<recursive_range>, "format_kind requires an input range");
65static_assert(std::format_kind<recursive_range> == std::range_format::disabled);
66
67static_assert(std::format_kind<std::filesystem::path> == std::range_format::disabled);
68
69static_assert(std::format_kind<std::map<int, int>> == std::range_format::map);
70static_assert(std::format_kind<std::multimap<int, int>> == std::range_format::map);
71static_assert(std::format_kind<std::unordered_map<int, int>> == std::range_format::map);
72static_assert(std::format_kind<std::unordered_multimap<int, int>> == std::range_format::map);
73
74static_assert(std::format_kind<std::set<int>> == std::range_format::set);
75static_assert(std::format_kind<std::multiset<int>> == std::range_format::set);
76static_assert(std::format_kind<std::unordered_set<int>> == std::range_format::set);
77static_assert(std::format_kind<std::unordered_multiset<int>> == std::range_format::set);
78
79static_assert(std::format_kind<std::array<int, 1>> == std::range_format::sequence);
80static_assert(std::format_kind<std::vector<int>> == std::range_format::sequence);
81static_assert(std::format_kind<std::deque<int>> == std::range_format::sequence);
82static_assert(std::format_kind<std::forward_list<int>> == std::range_format::sequence);
83static_assert(std::format_kind<std::list<int>> == std::range_format::sequence);
84
85static_assert(std::format_kind<std::span<int>> == std::range_format::sequence);
86
87static_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.
95struct no_specialization : std::ranges::view_base {
96 using key_type = void;
97 int* begin() const;
98 int* end() const;
99};
100static_assert(std::format_kind<no_specialization> == std::range_format::set);
101
102// The struct's "contents" are the same as no_specialization.
103struct specialized : std::ranges::view_base {
104 using key_type = void;
105 int* begin() const;
106 int* end() const;
107};
108
109template <>
110constexpr std::range_format std::format_kind<specialized> = std::range_format::sequence;
111static_assert(std::format_kind<specialized> == std::range_format::sequence);
112

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