37 template <
typename =
void>
struct node {
38 virtual ~node() =
default;
39 std::unique_ptr<node<>> next;
42 template <
typename T>
struct typed_node : node<> {
45 template <
typename Arg>
46 FMT_CONSTEXPR typed_node(
const Arg& arg) :
value(arg) {}
48 template <
typename Char>
50 :
value(arg.data(), arg.size()) {}
53 std::unique_ptr<node<>> head_;
56 template <
typename T,
typename Arg>
auto push(
const Arg& arg) ->
const T& {
57 auto new_node = std::unique_ptr<typed_node<T>>(
new typed_node<T>(arg));
58 auto&
value = new_node->value;
59 new_node->next = std::move(head_);
60 head_ = std::move(new_node);
78#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
84 using char_type =
typename Context::char_type;
86 template <
typename T>
struct need_copy {
87 static constexpr detail::type mapped_type =
92 std::is_same<T, basic_string_view<char_type>>::value ||
93 std::is_same<T, detail::std_string_view<char_type>>::value ||
94 (mapped_type != detail::type::cstring_type &&
95 mapped_type != detail::type::string_type &&
96 mapped_type != detail::type::custom_type))
100 template <
typename T>
101 using stored_type = conditional_t<
102 std::is_convertible<T, std::basic_string<char_type>>::value &&
104 std::basic_string<char_type>, T>;
107 std::vector<basic_format_arg<Context>> data_;
108 std::vector<detail::named_arg_info<char_type>> named_info_;
116 auto get_types()
const ->
unsigned long long {
117 return detail::is_unpacked_bit | data_.size() |
120 :
static_cast<unsigned long long>(detail::has_named_args_bit));
124 return named_info_.empty() ? data_.data() : data_.data() + 1;
127 template <
typename T>
void emplace_arg(
const T& arg) {
128 data_.emplace_back(detail::make_arg<Context>(arg));
131 template <
typename T>
133 if (named_info_.empty()) {
135 data_.insert(data_.begin(), {zero_ptr, 0});
137 data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
138 auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
141 std::unique_ptr<std::vector<basic_format_arg<Context>>,
decltype(pop_one)>
142 guard{&data_, pop_one};
143 named_info_.push_back({arg.name,
static_cast<int>(data_.size() - 2u)});
144 data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
169 if (detail::const_check(need_copy<T>::value))
170 emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
172 emplace_arg(detail::unwrap(arg));
190 template <
typename T>
void push_back(std::reference_wrapper<T> arg) {
193 "objects of built-in types and string views are always copied");
194 emplace_arg(arg.get());
202 template <
typename T>
204 const char_type* arg_name =
205 dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
206 if (detail::const_check(need_copy<T>::value)) {
208 fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
210 emplace_arg(fmt::arg(arg_name, arg.value));
227 void reserve(
size_t new_cap,
size_t new_cap_named) {
228 FMT_ASSERT(new_cap >= new_cap_named,
229 "Set of arguments includes set of named arguments");
230 data_.reserve(new_cap);
231 named_info_.reserve(new_cap_named);