Fixed a lifetime issue in test and minor build fixes.
This commit is contained in:
parent
833bfe3749
commit
c3c6d0c2d2
@ -159,8 +159,8 @@ class dynamic_format_arg_store
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
dynamic_format_arg_store() FMT_NOEXCEPT = default;
|
dynamic_format_arg_store() = default;
|
||||||
~dynamic_format_arg_store() FMT_NOEXCEPT = default;
|
~dynamic_format_arg_store() = default;
|
||||||
|
|
||||||
dynamic_format_arg_store(const dynamic_format_arg_store&) = delete;
|
dynamic_format_arg_store(const dynamic_format_arg_store&) = delete;
|
||||||
dynamic_format_arg_store& operator=(const dynamic_format_arg_store&) = delete;
|
dynamic_format_arg_store& operator=(const dynamic_format_arg_store&) = delete;
|
||||||
|
|||||||
@ -37,20 +37,25 @@ TEST(FormatDynArgsTest, StringsAndRefs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Custom{ int i{0}; };
|
struct Custom{ int i{0}; };
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct fmt::formatter<Custom> {
|
struct formatter<Custom> {
|
||||||
constexpr auto parse(format_parse_context& ctx) {
|
auto parse(format_parse_context& ctx) const -> decltype(ctx.begin())
|
||||||
|
{
|
||||||
return ctx.begin();
|
return ctx.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const Custom& p, FormatContext& ctx) {
|
auto format(const Custom& p, FormatContext& ctx) ->
|
||||||
// ctx.out() is an output iterator to write to.
|
decltype(format_to(ctx.out(),
|
||||||
return format_to(
|
std::declval<typename FormatContext::char_type const*>())) {
|
||||||
|
return format_to(
|
||||||
ctx.out(),
|
ctx.out(),
|
||||||
"cust={}", p.i);
|
"cust={}", p.i);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
#ifdef FMT_HAS_VARIANT
|
#ifdef FMT_HAS_VARIANT
|
||||||
|
|
||||||
@ -75,9 +80,19 @@ TEST(FormatDynArgsTest, CustomFormat) {
|
|||||||
|
|
||||||
TEST(FormatDynArgsTest, NamedArgByRef) {
|
TEST(FormatDynArgsTest, NamedArgByRef) {
|
||||||
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||||
auto a1 = fmt::arg("a1_", 42);
|
|
||||||
auto ref = std::cref(a1);
|
// Note: fmt::arg() constructs an object which holds a reference
|
||||||
store.push_back(ref);
|
// to its value. It's not an aggregate, so it doesn't extend the
|
||||||
|
// reference lifetime. As a result, it's a very bad idea passing temporary
|
||||||
|
// as a named argument value. Only GCC with optimization level >0
|
||||||
|
// complains about this.
|
||||||
|
//
|
||||||
|
// A real life usecase is when you have both name and value alive
|
||||||
|
// guarantee their lifetime and thus don't want them to be copied into
|
||||||
|
// storages.
|
||||||
|
int a1_val{42};
|
||||||
|
auto a1 = fmt::arg("a1_", a1_val);
|
||||||
|
store.push_back(std::cref(a1));
|
||||||
|
|
||||||
std::string result = fmt::vformat(
|
std::string result = fmt::vformat(
|
||||||
"{a1_}", // and {} and {}",
|
"{a1_}", // and {} and {}",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user