diff --git a/include/fmt/dyn-args.h b/include/fmt/dyn-args.h index e9ac5378..58e347dc 100644 --- a/include/fmt/dyn-args.h +++ b/include/fmt/dyn-args.h @@ -58,21 +58,26 @@ class dyn_arg_storage { // doesn't complain about inability to deduce translation unit to place vtable // So dyn_arg_node_base is made a fake template - template - struct dyn_arg_node_base { - virtual ~dyn_arg_node_base() = default; - std::unique_ptr next_; + template struct storage_node_base { + using owning_ptr = std::unique_ptr>; + virtual ~storage_node_base() = default; + owning_ptr next_; }; - template - struct dyn_arg_node : dyn_arg_node_base<> { + using owning_ptr = storage_node_base<>::owning_ptr; + + template struct storage_node : storage_node_base<> { T value_; - FMT_CONSTEXPR explicit dyn_arg_node(T&& arg) : value_{arg}{} + FMT_CONSTEXPR explicit storage_node(const T& arg, owning_ptr&& next) + : value_{arg} { + // Must be initialised after value_ + next_ = std::move(next); + } }; - std::unique_ptr> head_{nullptr}; + owning_ptr head_{nullptr}; -public: + public: dyn_arg_storage() = default; dyn_arg_storage(const dyn_arg_storage&) = delete; dyn_arg_storage(dyn_arg_storage&&) = default; @@ -80,12 +85,9 @@ public: dyn_arg_storage& operator=(const dyn_arg_storage&) = delete; dyn_arg_storage& operator=(dyn_arg_storage&&) = default; - template - const T& emplace_front(T&& val) { - auto node = new dyn_arg_node{std::forward(val)}; - std::unique_ptr> ptr{node}; - swap(ptr, head_); - head_->next_ = std::move(ptr); + template const T& push(const Arg& arg) { + auto node = new storage_node{arg, std::move(head_)}; + head_.reset(node); return node->value_; } }; @@ -115,7 +117,7 @@ class dynamic_format_arg_store using value_type = basic_format_arg; template - using storaged_type = + using stored_type = conditional_t::value, string_type, T>; // Storage of basic_format_arg must be contiguous @@ -143,8 +145,8 @@ class dynamic_format_arg_store } template - const storaged_type& stored_value(const T& arg, std::true_type) { - return storage_.emplace_front(storaged_type{arg}); + const stored_type& stored_value(const T& arg, std::true_type) { + return storage_.push>(arg); } template void emplace_arg(const T& arg) { @@ -162,6 +164,9 @@ class dynamic_format_arg_store dynamic_format_arg_store& operator=(dynamic_format_arg_store&&) = default; template void push_back(const T& arg) { + static_assert( + !std::is_base_of, T>::value, + "Named arguments are not supported yet"); emplace_arg(stored_value(arg, internal::need_dyn_copy_t{})); } diff --git a/test/format-dyn-args-test.cc b/test/format-dyn-args-test.cc index 21478865..76e351d4 100644 --- a/test/format-dyn-args-test.cc +++ b/test/format-dyn-args-test.cc @@ -52,10 +52,6 @@ FMT_END_NAMESPACE TEST(FormatDynArgsTest, CustomFormat) { using context = fmt::format_context; fmt::dynamic_format_arg_store store; - static_assert(fmt::internal::need_dyn_copy_t::value, ""); - static_assert( - fmt::internal::mapped_type_constant::value == - fmt::internal::type::custom_type, ""); custom_type c{}; store.push_back(c); ++c.i;