quill
DynamicFormatArgStore.h
1 
7 #pragma once
8 
9 #include <memory>
10 #include <string>
11 #include <string_view>
12 #include <type_traits>
13 #include <vector>
14 
15 #include "quill/bundled/fmt/base.h"
16 #include "quill/core/Attributes.h"
17 
18 QUILL_BEGIN_NAMESPACE
19 
20 namespace detail
21 {
23 {
24  struct Node
25  {
26  virtual ~Node() = default;
27  std::unique_ptr<Node> next;
28  };
29 
30  template <typename T>
31  struct TypedNode : Node
32  {
33  template <typename Arg>
34  explicit TypedNode(Arg&& arg) : value(_construct(static_cast<Arg&&>(arg)))
35  {
36  }
37 
38  private:
39  template <typename Arg>
40  static T _construct(Arg&& arg)
41  {
42  if constexpr (std::is_move_constructible<T>::value)
43  {
44  return T(static_cast<Arg&&>(arg));
45  }
46  else
47  {
48  // For copy-only types: arg is a named rvalue reference, which is an lvalue expression.
49  // This lvalue can bind to const T& (the copy constructor parameter), resulting in a copy.
50  return T(arg);
51  }
52  }
53 
54  public:
55  T value;
56  };
57 
58  std::unique_ptr<Node> _head;
59 
60 public:
61  template <typename T, typename Arg>
62  T const& push(Arg&& arg)
63  {
64  auto new_node = std::unique_ptr<TypedNode<T>>(new TypedNode<T>(static_cast<Arg&&>(arg)));
65  T& value = new_node->value;
66  new_node->next = static_cast<std::unique_ptr<Node>&&>(_head);
67  _head = static_cast<std::unique_ptr<TypedNode<T>>&&>(new_node);
68  return value;
69  }
70 };
71 } // namespace detail
72 
78 {
79 private:
80  // Storage of basic_format_arg must be contiguous.
81  std::vector<fmtquill::basic_format_arg<fmtquill::format_context>> _data;
82 
83  // Storage of arguments not fitting into basic_format_arg must grow
84  // without relocation because items in data_ refer to it.
85  detail::DynamicArgList _dynamic_arg_list;
86  bool _has_string_related_type{false};
87 
88  template <typename T>
89  void emplace_arg(T&& arg)
90  {
91  _data.emplace_back(static_cast<T&&>(arg));
92  }
93 
94 public:
95  DynamicFormatArgStore() = default;
96 
97  QUILL_NODISCARD int size() const { return static_cast<int>(_data.size()); }
98 
99  QUILL_NODISCARD fmtquill::basic_format_arg<fmtquill::format_context> const* data() const
100  {
101  return _data.data();
102  }
103 
115  template <typename T>
116  void push_back(T&& arg)
117  {
118  using char_type = typename fmtquill::format_context::char_type;
119  using bare_type = std::remove_cv_t<std::remove_reference_t<T>>;
120  constexpr auto mapped_type = fmtquill::detail::mapped_type_constant<bare_type, char_type>::value;
121  using stored_type =
122  std::conditional_t<std::is_convertible_v<bare_type, std::string>, std::string, bare_type>;
123 
124  if constexpr (!(std::is_same_v<bare_type, std::string_view> || std::is_same_v<bare_type, fmtquill::string_view> ||
125  (mapped_type != fmtquill::detail::type::cstring_type &&
126  mapped_type != fmtquill::detail::type::string_type &&
127  mapped_type != fmtquill::detail::type::custom_type)))
128  {
129  emplace_arg(_dynamic_arg_list.push<stored_type>(static_cast<T&&>(arg)));
130  }
131  else
132  {
133  emplace_arg(static_cast<T&&>(arg));
134  }
135 
136  if constexpr (std::is_same_v<bare_type, std::string_view> || std::is_same_v<bare_type, fmtquill::string_view> ||
137  (mapped_type == fmtquill::detail::type::cstring_type) ||
138  (mapped_type == fmtquill::detail::type::string_type) ||
139  (mapped_type == fmtquill::detail::type::custom_type) ||
140  (mapped_type == fmtquill::detail::type::char_type))
141  {
142  _has_string_related_type = true;
143  }
144  }
145 
147  void clear()
148  {
149  _data.clear();
150  _dynamic_arg_list = detail::DynamicArgList{};
151  _has_string_related_type = false;
152  }
153 
154  QUILL_NODISCARD bool has_string_related_type() const noexcept { return _has_string_related_type; }
155 };
156 
157 QUILL_END_NAMESPACE
void clear()
Erase all elements from the store.
Definition: DynamicFormatArgStore.h:147
char char_type
The character type for the output.
Definition: base.h:2710
Definition: DynamicFormatArgStore.h:22
Similar to fmt::dynamic_arg_store but better suited to our needs e.g does not include <functional> an...
Definition: DynamicFormatArgStore.h:77
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
Definition: base.h:2198
void push_back(T &&arg)
Adds an argument for later passing to a formatting function.
Definition: DynamicFormatArgStore.h:116