spdlog
Loading...
Searching...
No Matches
args.h
Go to the documentation of this file.
1// Formatting library for C++ - dynamic format arguments
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
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> const T& unwrap(const T& v) { return v; }
26template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) {
27 return static_cast<const T&>(v);
28}
29
31 // Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
32 // templates it doesn't complain about inability to deduce single translation
33 // unit for placing vtable. So storage_node_base is made a fake template.
34 template <typename = void> struct node {
35 virtual ~node() = default;
37 };
38
39 template <typename T> struct typed_node : node<> {
41
42 template <typename Arg>
44
45 template <typename Char>
48 };
49
51
52 public:
53 template <typename T, typename Arg> const T& push(const Arg& arg) {
54 auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
55 auto& value = new_node->value;
56 new_node->next = std::move(head_);
57 head_ = std::move(new_node);
58 return value;
59 }
60};
61} // namespace detail
62
63/**
64 \rst
65 A dynamic version of `fmt::format_arg_store`.
66 It's equipped with a storage to potentially temporary objects which lifetimes
67 could be shorter than the format arguments object.
68
69 It can be implicitly converted into `~fmt::basic_format_args` for passing
70 into type-erased formatting functions such as `~fmt::vformat`.
71 \endrst
72 */
73template <typename Context>
76 // Workaround a GCC template argument substitution bug.
78#endif
79{
80 private:
81 using char_type = typename Context::char_type;
82
83 template <typename T> struct need_copy {
84 static constexpr detail::type mapped_type =
85 detail::mapped_type_constant<T, Context>::value;
86
87 enum {
91 (mapped_type != detail::type::cstring_type &&
92 mapped_type != detail::type::string_type &&
93 mapped_type != detail::type::custom_type))
94 };
95 };
96
97 template <typename T>
102
103 // Storage of basic_format_arg must be contiguous.
106
107 // Storage of arguments not fitting into basic_format_arg must grow
108 // without relocation because items in data_ refer to it.
110
111 friend class basic_format_args<Context>;
112
113 unsigned long long get_types() const {
114 return detail::is_unpacked_bit | data_.size() |
115 (named_info_.empty()
116 ? 0ULL
117 : static_cast<unsigned long long>(detail::has_named_args_bit));
118 }
119
121 return named_info_.empty() ? data_.data() : data_.data() + 1;
122 }
123
124 template <typename T> void emplace_arg(const T& arg) {
125 data_.emplace_back(detail::make_arg<Context>(arg));
126 }
127
128 template <typename T>
129 void emplace_arg(const detail::named_arg<char_type, T>& arg) {
130 if (named_info_.empty()) {
131 constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};
132 data_.insert(data_.begin(), {zero_ptr, 0});
133 }
134 data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
135 auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
136 data->pop_back();
137 };
139 guard{&data_, pop_one};
140 named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
141 data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
142 guard.release();
143 }
144
145 public:
146 /**
147 \rst
148 Adds an argument into the dynamic store for later passing to a formatting
149 function.
150
151 Note that custom types and string types (but not string views) are copied
152 into the store dynamically allocating memory if necessary.
153
154 **Example**::
155
156 fmt::dynamic_format_arg_store<fmt::format_context> store;
157 store.push_back(42);
158 store.push_back("abc");
159 store.push_back(1.5f);
160 std::string result = fmt::vformat("{} and {} and {}", store);
161 \endrst
162 */
163 template <typename T> void push_back(const T& arg) {
164 if (detail::const_check(need_copy<T>::value))
165 emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
166 else
167 emplace_arg(detail::unwrap(arg));
168 }
169
170 /**
171 \rst
172 Adds a reference to the argument into the dynamic store for later passing to
173 a formatting function.
174
175 **Example**::
176
177 fmt::dynamic_format_arg_store<fmt::format_context> store;
178 char band[] = "Rolling Stones";
179 store.push_back(std::cref(band));
180 band[9] = 'c'; // Changing str affects the output.
181 std::string result = fmt::vformat("{}", store);
182 // result == "Rolling Scones"
183 \endrst
184 */
185 template <typename T> void push_back(std::reference_wrapper<T> arg) {
186 static_assert(
188 "objects of built-in types and string views are always copied");
189 emplace_arg(arg.get());
190 }
191
192 /**
193 Adds named argument into the dynamic store for later passing to a formatting
194 function. ``std::reference_wrapper`` is supported to avoid copying of the
195 argument. The name is always copied into the store.
196 */
197 template <typename T>
198 void push_back(const detail::named_arg<char_type, T>& arg) {
199 const char_type* arg_name =
200 dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
201 if (detail::const_check(need_copy<T>::value)) {
202 emplace_arg(
203 fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
204 } else {
205 emplace_arg(fmt::arg(arg_name, arg.value));
206 }
207 }
208
209 /** Erase all elements from the store */
210 void clear() {
211 data_.clear();
212 named_info_.clear();
213 dynamic_args_ = detail::dynamic_arg_list();
214 }
215
216 /**
217 \rst
218 Reserves space to store at least *new_cap* arguments including
219 *new_cap_named* named arguments.
220 \endrst
221 */
222 void reserve(size_t new_cap, size_t new_cap_named) {
223 FMT_ASSERT(new_cap >= new_cap_named,
224 "Set of arguments includes set of named arguments");
225 data_.reserve(new_cap);
226 named_info_.reserve(new_cap_named);
227 }
228};
229
231
232#endif // FMT_ARGS_H_
T begin(T... args)
const T & push(const Arg &arg)
Definition args.h:53
std::unique_ptr< node<> > head_
Definition args.h:50
void emplace_arg(const detail::named_arg< char_type, T > &arg)
Definition args.h:129
void push_back(const detail::named_arg< char_type, T > &arg)
Definition args.h:198
typename Context::char_type char_type
Definition args.h:81
void emplace_arg(const T &arg)
Definition args.h:124
unsigned long long get_types() const
Definition args.h:113
conditional_t< detail::is_string< T >::value &&!has_formatter< T, Context >::value &&!detail::is_reference_wrapper< T >::value, std::basic_string< char_type >, T > stored_type
Definition args.h:101
void push_back(const T &arg)
Definition args.h:163
const basic_format_arg< Context > * data() const
Definition args.h:120
std::vector< basic_format_arg< Context > > data_
Definition args.h:104
void reserve(size_t new_cap, size_t new_cap_named)
Definition args.h:222
void push_back(std::reference_wrapper< T > arg)
Definition args.h:185
std::vector< detail::named_arg_info< char_type > > named_info_
Definition args.h:105
Definition core.h:1120
constexpr FMT_INLINE value()
Definition core.h:1143
T clear(T... args)
#define FMT_ASSERT(condition, message)
Definition core.h:372
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition core.h:1725
#define FMT_GCC_VERSION
Definition core.h:31
#define FMT_CONSTEXPR
Definition core.h:99
#define FMT_BEGIN_NAMESPACE
Definition core.h:235
typename std::conditional< B, T, F >::type conditional_t
Definition core.h:323
T
Definition core.h:320
#define FMT_END_NAMESPACE
Definition core.h:230
T data(T... args)
T emplace_back(T... args)
T empty(T... args)
T insert(T... args)
Definition args.h:19
const T & unwrap(const T &v)
Definition args.h:25
T push_back(T... args)
T reserve(T... args)
T size(T... args)
Definition format.h:897
std::unique_ptr< node<> > next
Definition args.h:36
FMT_CONSTEXPR typed_node(const Arg &arg)
Definition args.h:43
FMT_CONSTEXPR typed_node(const basic_string_view< Char > &arg)
Definition args.h:46