enum_name
Loading...
Searching...
No Matches
args.h
1// Formatting library for C++ - dynamic argument lists
2//
3// Copyright (c) 2012 - present, Victor Zverovich
4// All rights reserved.
5//
6// For the license information refer to format.h.
7
8#ifndef FMT_ARGS_H_
9#define FMT_ARGS_H_
10
11#include <functional> // std::reference_wrapper
12#include <memory> // std::unique_ptr
13#include <vector>
14
15#include "core.h"
16
17FMT_BEGIN_NAMESPACE
18
19namespace detail {
20
21template <typename T> struct is_reference_wrapper : std::false_type {};
22template <typename T>
23struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
24
25template <typename T> auto unwrap(const T& v) -> const T& { return v; }
26template <typename T>
27auto unwrap(const std::reference_wrapper<T>& v) -> const T& {
28 return static_cast<const T&>(v);
29}
30
32 // Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
33 // templates it doesn't complain about inability to deduce single translation
34 // unit for placing vtable. So storage_node_base is made a fake template.
35 template <typename = void> struct node {
36 virtual ~node() = default;
37 std::unique_ptr<node<>> next;
38 };
39
40 template <typename T> struct typed_node : node<> {
41 T value;
42
43 template <typename Arg>
44 FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}
45
46 template <typename Char>
47 FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg)
48 : value(arg.data(), arg.size()) {}
49 };
50
51 std::unique_ptr<node<>> head_;
52
53 public:
54 template <typename T, typename Arg> auto push(const Arg& arg) -> const T& {
55 auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
56 auto& value = new_node->value;
57 new_node->next = std::move(head_);
58 head_ = std::move(new_node);
59 return value;
60 }
61};
62} // namespace detail
63
74template <typename Context>
76#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
77 // Workaround a GCC template argument substitution bug.
79#endif
80{
81 private:
82 using char_type = typename Context::char_type;
83
84 template <typename T> struct need_copy {
85 static constexpr detail::type mapped_type =
87
88 enum {
90 std::is_same<T, basic_string_view<char_type>>::value ||
91 std::is_same<T, detail::std_string_view<char_type>>::value ||
92 (mapped_type != detail::type::cstring_type &&
93 mapped_type != detail::type::string_type &&
94 mapped_type != detail::type::custom_type))
95 };
96 };
97
98 template <typename T>
99 using stored_type = conditional_t<
100 std::is_convertible<T, std::basic_string<char_type>>::value &&
102 std::basic_string<char_type>, T>;
103
104 // Storage of basic_format_arg must be contiguous.
105 std::vector<basic_format_arg<Context>> data_;
106 std::vector<detail::named_arg_info<char_type>> named_info_;
107
108 // Storage of arguments not fitting into basic_format_arg must grow
109 // without relocation because items in data_ refer to it.
110 detail::dynamic_arg_list dynamic_args_;
111
112 friend class basic_format_args<Context>;
113
114 auto get_types() const -> unsigned long long {
115 return detail::is_unpacked_bit | data_.size() |
116 (named_info_.empty()
117 ? 0ULL
118 : static_cast<unsigned long long>(detail::has_named_args_bit));
119 }
120
121 auto data() const -> const basic_format_arg<Context>* {
122 return named_info_.empty() ? data_.data() : data_.data() + 1;
123 }
124
125 template <typename T> void emplace_arg(const T& arg) {
126 data_.emplace_back(detail::make_arg<Context>(arg));
127 }
128
129 template <typename T>
130 void emplace_arg(const detail::named_arg<char_type, T>& arg) {
131 if (named_info_.empty()) {
132 constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};
133 data_.insert(data_.begin(), {zero_ptr, 0});
134 }
135 data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
136 auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
137 data->pop_back();
138 };
139 std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
140 guard{&data_, pop_one};
141 named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
142 data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
143 guard.release();
144 }
145
146 public:
147 constexpr dynamic_format_arg_store() = default;
148
166 template <typename T> void push_back(const T& arg) {
167 if (detail::const_check(need_copy<T>::value))
168 emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
169 else
170 emplace_arg(detail::unwrap(arg));
171 }
172
188 template <typename T> void push_back(std::reference_wrapper<T> arg) {
189 static_assert(
190 need_copy<T>::value,
191 "objects of built-in types and string views are always copied");
192 emplace_arg(arg.get());
193 }
194
200 template <typename T>
202 const char_type* arg_name =
203 dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
204 if (detail::const_check(need_copy<T>::value)) {
205 emplace_arg(
206 fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
207 } else {
208 emplace_arg(fmt::arg(arg_name, arg.value));
209 }
210 }
211
213 void clear() {
214 data_.clear();
215 named_info_.clear();
216 dynamic_args_ = detail::dynamic_arg_list();
217 }
218
225 void reserve(size_t new_cap, size_t new_cap_named) {
226 FMT_ASSERT(new_cap >= new_cap_named,
227 "Set of arguments includes set of named arguments");
228 data_.reserve(new_cap);
229 named_info_.reserve(new_cap_named);
230 }
231};
232
233FMT_END_NAMESPACE
234
235#endif // FMT_ARGS_H_
Definition core.h:1627
Definition core.h:1891
Definition core.h:415
Definition args.h:31
Definition core.h:1257
Definition args.h:80
void push_back(const detail::named_arg< char_type, T > &arg)
Definition args.h:201
void push_back(const T &arg)
Definition args.h:166
void clear()
Definition args.h:213
void reserve(size_t new_cap, size_t new_cap_named)
Definition args.h:225
void push_back(std::reference_wrapper< T > arg)
Definition args.h:188
Definition args.h:21
Definition core.h:1162
Definition core.h:1156
Definition core.h:598