Improve exception safety in dynamic_format_arg_store

This commit is contained in:
Victor Zverovich 2020-03-21 08:51:48 -07:00
parent 2951169481
commit dd97f4920c
2 changed files with 33 additions and 8 deletions

View File

@ -284,7 +284,7 @@ FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
#ifndef FMT_ASSERT #ifndef FMT_ASSERT
# ifdef NDEBUG # ifdef NDEBUG
// FMT_ASSERT is not empty to avoid -Werror=empty-body. // FMT_ASSERT is not empty to avoid -Werror=empty-body.
# define FMT_ASSERT(condition, message) ((void)0) # define FMT_ASSERT(condition, message) ((void)0)
# else # else
# define FMT_ASSERT(condition, message) \ # define FMT_ASSERT(condition, message) \
@ -1236,11 +1236,11 @@ class dynamic_arg_list {
public: public:
template <typename T, typename Arg> const T& push(const Arg& arg) { template <typename T, typename Arg> const T& push(const Arg& arg) {
auto next = std::move(head_); auto node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
auto node = new typed_node<T>(arg); auto& value = node->value;
head_.reset(node); node->next = std::move(head_);
head_->next = std::move(next); head_ = std::move(node);
return node->value; return value;
} }
}; };
} // namespace internal } // namespace internal

View File

@ -435,8 +435,7 @@ template <> struct formatter<custom_type> {
} }
template <typename FormatContext> template <typename FormatContext>
auto format(const custom_type& p, FormatContext& ctx) -> decltype(format_to( auto format(const custom_type& p, FormatContext& ctx) -> decltype(ctx.out()) {
ctx.out(), std::declval<typename FormatContext::char_type const*>())) {
return format_to(ctx.out(), "cust={}", p.i); return format_to(ctx.out(), "cust={}", p.i);
} }
}; };
@ -478,6 +477,32 @@ TEST(FormatDynArgsTest, NamedArgByRef) {
EXPECT_EQ("42", result); EXPECT_EQ("42", result);
} }
struct copy_throwable {
copy_throwable() {}
copy_throwable(const copy_throwable&) { throw "deal with it"; }
};
FMT_BEGIN_NAMESPACE
template <> struct formatter<copy_throwable> {
auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
return ctx.begin();
}
auto format(copy_throwable, format_context& ctx) -> decltype(ctx.out()) {
return ctx.out();
}
};
FMT_END_NAMESPACE
TEST(FormatDynArgsTest, ThrowOnCopy) {
fmt::dynamic_format_arg_store<fmt::format_context> store;
store.push_back(std::string("foo"));
try {
store.push_back(copy_throwable());
} catch (...) {
}
EXPECT_EQ(fmt::vformat("{}", store), "foo");
}
TEST(StringViewTest, ValueType) { TEST(StringViewTest, ValueType) {
static_assert(std::is_same<string_view::value_type, char>::value, ""); static_assert(std::is_same<string_view::value_type, char>::value, "");
} }