mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-25 06:21:00 +00:00
Improve exception safety in dynamic_format_arg_store
This commit is contained in:
parent
2951169481
commit
dd97f4920c
@ -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
|
||||||
|
@ -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, "");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user