Compose Arg instead of inheriting from Value
This commit is contained in:
parent
5c76d107cb
commit
8a9ad00ab3
18
format.cc
18
format.cc
@ -304,20 +304,20 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
|
||||
// Extra casts are used to silence warnings.
|
||||
if (is_signed) {
|
||||
arg_.type = Arg::INT;
|
||||
arg_.int_value = static_cast<int>(static_cast<T>(value));
|
||||
arg_.value.int_value = static_cast<int>(static_cast<T>(value));
|
||||
} else {
|
||||
arg_.type = Arg::UINT;
|
||||
arg_.uint_value = static_cast<unsigned>(
|
||||
arg_.value.uint_value = static_cast<unsigned>(
|
||||
static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
|
||||
}
|
||||
} else {
|
||||
if (is_signed) {
|
||||
arg_.type = Arg::LONG_LONG;
|
||||
arg_.long_long_value =
|
||||
arg_.value.long_long_value =
|
||||
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
|
||||
} else {
|
||||
arg_.type = Arg::ULONG_LONG;
|
||||
arg_.ulong_long_value =
|
||||
arg_.value.ulong_long_value =
|
||||
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
|
||||
}
|
||||
}
|
||||
@ -337,7 +337,7 @@ class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
|
||||
template <typename T>
|
||||
void visit_any_int(T value) {
|
||||
arg_.type = Arg::CHAR;
|
||||
arg_.int_value = static_cast<char>(value);
|
||||
arg_.value.int_value = static_cast<char>(value);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
@ -405,7 +405,7 @@ class PrintfArgFormatter :
|
||||
write_null_pointer();
|
||||
}
|
||||
|
||||
void visit_custom(Arg::CustomValue c) {
|
||||
void visit_custom(Value::CustomValue c) {
|
||||
BasicFormatter<Char> formatter(ArgList(), this->writer());
|
||||
const Char format_str[] = {'}', 0};
|
||||
const Char *format = format_str;
|
||||
@ -627,7 +627,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
|
||||
for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
|
||||
internal::Arg::Type arg_type = args.type(i);
|
||||
if (arg_type == internal::Arg::NAMED_ARG) {
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].value.pointer);
|
||||
map_.insert(Pair(named_arg->name, *named_arg));
|
||||
}
|
||||
}
|
||||
@ -636,7 +636,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
|
||||
case internal::Arg::NONE:
|
||||
return;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].value.pointer);
|
||||
map_.insert(Pair(named_arg->name, *named_arg));
|
||||
break;
|
||||
default:
|
||||
@ -658,7 +658,7 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
|
||||
error = "argument index out of range";
|
||||
break;
|
||||
case Arg::NAMED_ARG:
|
||||
arg = *static_cast<const internal::Arg*>(arg.pointer);
|
||||
arg = *static_cast<const internal::Arg*>(arg.value.pointer);
|
||||
default:
|
||||
/*nothing*/;
|
||||
}
|
||||
|
||||
109
format.h
109
format.h
@ -927,7 +927,11 @@ struct Value {
|
||||
StringValue<wchar_t> wstring;
|
||||
CustomValue custom;
|
||||
};
|
||||
};
|
||||
|
||||
// A formatting argument. It is a POD type to allow storage in
|
||||
// internal::MemoryBuffer.
|
||||
struct Arg {
|
||||
enum Type {
|
||||
NONE, NAMED_ARG,
|
||||
// Integer types should go first,
|
||||
@ -936,11 +940,8 @@ struct Value {
|
||||
DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
|
||||
CSTRING, STRING, WSTRING, POINTER, CUSTOM
|
||||
};
|
||||
};
|
||||
|
||||
// A formatting argument. It is a POD type to allow storage in
|
||||
// internal::MemoryBuffer.
|
||||
struct Arg : Value {
|
||||
Value value;
|
||||
Type type;
|
||||
};
|
||||
|
||||
@ -1044,7 +1045,7 @@ struct Not<false> { enum { value = 1 }; };
|
||||
|
||||
// Makes an Arg object from any type.
|
||||
template <typename Formatter>
|
||||
class MakeValue : public Arg {
|
||||
class MakeValue : public Value {
|
||||
public:
|
||||
typedef typename Formatter::Char Char;
|
||||
|
||||
@ -1206,9 +1207,10 @@ struct NamedArg : Arg {
|
||||
typedef internal::MakeValue< BasicFormatter<Char> > MakeValue;
|
||||
|
||||
template <typename T>
|
||||
NamedArg(BasicStringRef<Char> argname, const T &value)
|
||||
: Arg(MakeValue(value)), name(argname) {
|
||||
type = static_cast<Arg::Type>(MakeValue::type(value));
|
||||
NamedArg(BasicStringRef<Char> argname, const T &x)
|
||||
: name(argname) {
|
||||
value = MakeValue(x);
|
||||
type = static_cast<Arg::Type>(MakeValue::type(x));
|
||||
}
|
||||
};
|
||||
|
||||
@ -1281,16 +1283,16 @@ class ArgVisitor {
|
||||
Result visit_cstring(const char *) {
|
||||
return FMT_DISPATCH(visit_unhandled_arg());
|
||||
}
|
||||
Result visit_string(Arg::StringValue<char>) {
|
||||
Result visit_string(Value::StringValue<char>) {
|
||||
return FMT_DISPATCH(visit_unhandled_arg());
|
||||
}
|
||||
Result visit_wstring(Arg::StringValue<wchar_t>) {
|
||||
Result visit_wstring(Value::StringValue<wchar_t>) {
|
||||
return FMT_DISPATCH(visit_unhandled_arg());
|
||||
}
|
||||
Result visit_pointer(const void *) {
|
||||
return FMT_DISPATCH(visit_unhandled_arg());
|
||||
}
|
||||
Result visit_custom(Arg::CustomValue) {
|
||||
Result visit_custom(Value::CustomValue) {
|
||||
return FMT_DISPATCH(visit_unhandled_arg());
|
||||
}
|
||||
|
||||
@ -1300,31 +1302,31 @@ class ArgVisitor {
|
||||
FMT_ASSERT(false, "invalid argument type");
|
||||
return Result();
|
||||
case Arg::INT:
|
||||
return FMT_DISPATCH(visit_int(arg.int_value));
|
||||
return FMT_DISPATCH(visit_int(arg.value.int_value));
|
||||
case Arg::UINT:
|
||||
return FMT_DISPATCH(visit_uint(arg.uint_value));
|
||||
return FMT_DISPATCH(visit_uint(arg.value.uint_value));
|
||||
case Arg::LONG_LONG:
|
||||
return FMT_DISPATCH(visit_long_long(arg.long_long_value));
|
||||
return FMT_DISPATCH(visit_long_long(arg.value.long_long_value));
|
||||
case Arg::ULONG_LONG:
|
||||
return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value));
|
||||
return FMT_DISPATCH(visit_ulong_long(arg.value.ulong_long_value));
|
||||
case Arg::BOOL:
|
||||
return FMT_DISPATCH(visit_bool(arg.int_value != 0));
|
||||
return FMT_DISPATCH(visit_bool(arg.value.int_value != 0));
|
||||
case Arg::CHAR:
|
||||
return FMT_DISPATCH(visit_char(arg.int_value));
|
||||
return FMT_DISPATCH(visit_char(arg.value.int_value));
|
||||
case Arg::DOUBLE:
|
||||
return FMT_DISPATCH(visit_double(arg.double_value));
|
||||
return FMT_DISPATCH(visit_double(arg.value.double_value));
|
||||
case Arg::LONG_DOUBLE:
|
||||
return FMT_DISPATCH(visit_long_double(arg.long_double_value));
|
||||
return FMT_DISPATCH(visit_long_double(arg.value.long_double_value));
|
||||
case Arg::CSTRING:
|
||||
return FMT_DISPATCH(visit_cstring(arg.string.value));
|
||||
return FMT_DISPATCH(visit_cstring(arg.value.string.value));
|
||||
case Arg::STRING:
|
||||
return FMT_DISPATCH(visit_string(arg.string));
|
||||
return FMT_DISPATCH(visit_string(arg.value.string));
|
||||
case Arg::WSTRING:
|
||||
return FMT_DISPATCH(visit_wstring(arg.wstring));
|
||||
return FMT_DISPATCH(visit_wstring(arg.value.wstring));
|
||||
case Arg::POINTER:
|
||||
return FMT_DISPATCH(visit_pointer(arg.pointer));
|
||||
return FMT_DISPATCH(visit_pointer(arg.value.pointer));
|
||||
case Arg::CUSTOM:
|
||||
return FMT_DISPATCH(visit_custom(arg.custom));
|
||||
return FMT_DISPATCH(visit_custom(arg.value.custom));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1385,9 +1387,8 @@ class ArgList {
|
||||
bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE;
|
||||
if (index < MAX_PACKED_ARGS) {
|
||||
Arg::Type arg_type = type(index);
|
||||
internal::Value &val = arg;
|
||||
if (arg_type != Arg::NONE)
|
||||
val = use_values ? values_[index] : args_[index];
|
||||
arg.value = use_values ? values_[index] : args_[index].value;
|
||||
arg.type = arg_type;
|
||||
return arg;
|
||||
}
|
||||
@ -1665,12 +1666,12 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
|
||||
|
||||
void write(bool value) {
|
||||
const char *str_value = value ? "true" : "false";
|
||||
Arg::StringValue<char> str = { str_value, std::strlen(str_value) };
|
||||
Value::StringValue<char> str = { str_value, std::strlen(str_value) };
|
||||
writer_.write_str(str, spec_);
|
||||
}
|
||||
|
||||
void write(const char *value) {
|
||||
Arg::StringValue<char> str = {value, value != 0 ? std::strlen(value) : 0};
|
||||
Value::StringValue<char> str = {value, value != 0 ? std::strlen(value) : 0};
|
||||
writer_.write_str(str, spec_);
|
||||
}
|
||||
|
||||
@ -1726,13 +1727,13 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
|
||||
write(value);
|
||||
}
|
||||
|
||||
void visit_string(Arg::StringValue<char> value) {
|
||||
void visit_string(Value::StringValue<char> value) {
|
||||
writer_.write_str(value, spec_);
|
||||
}
|
||||
|
||||
using ArgVisitor<Impl, void>::visit_wstring;
|
||||
|
||||
void visit_wstring(Arg::StringValue<Char> value) {
|
||||
void visit_wstring(Value::StringValue<Char> value) {
|
||||
writer_.write_str(value, spec_);
|
||||
}
|
||||
|
||||
@ -1756,7 +1757,7 @@ class BasicArgFormatter :
|
||||
: ArgFormatterBase<BasicArgFormatter<Char>, Char>(f.writer(), s),
|
||||
formatter_(f), format_(fmt) {}
|
||||
|
||||
void visit_custom(Arg::CustomValue c) {
|
||||
void visit_custom(Value::CustomValue c) {
|
||||
c.format(&formatter_, c.value, &format_);
|
||||
}
|
||||
};
|
||||
@ -1931,12 +1932,15 @@ inline void set_types(Value *, const Args & ...) {
|
||||
template <typename Formatter, typename Value>
|
||||
inline void store_args(Value *) {}
|
||||
|
||||
template <typename Formatter, typename Arg, typename T, typename... Args>
|
||||
template <typename Formatter, typename T, typename... Args>
|
||||
inline void store_args(Arg *args, const T &arg, const Args & ... tail) {
|
||||
// Assign only the Value subobject of Arg and don't overwrite type (if any)
|
||||
// that is assigned by set_types.
|
||||
Value &value = *args;
|
||||
value = MakeValue<Formatter>(arg);
|
||||
args->value = MakeValue<Formatter>(arg);
|
||||
store_args<Formatter>(args + 1, tail...);
|
||||
}
|
||||
|
||||
template <typename Formatter, typename T, typename... Args>
|
||||
inline void store_args(Value *args, const T &arg, const Args & ... tail) {
|
||||
*args = MakeValue<Formatter>(arg);
|
||||
store_args<Formatter>(args + 1, tail...);
|
||||
}
|
||||
|
||||
@ -2242,7 +2246,7 @@ class BasicWriter {
|
||||
CharPtr write_str(const StrChar *s, std::size_t size, const AlignSpec &spec);
|
||||
|
||||
template <typename StrChar>
|
||||
void write_str(const internal::Arg::StringValue<StrChar> &str,
|
||||
void write_str(const internal::Value::StringValue<StrChar> &str,
|
||||
const FormatSpec &spec);
|
||||
|
||||
// This following methods are private to disallow writing wide characters
|
||||
@ -2461,7 +2465,7 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
|
||||
template <typename Char>
|
||||
template <typename StrChar>
|
||||
void BasicWriter<Char>::write_str(
|
||||
const internal::Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
|
||||
const internal::Value::StringValue<StrChar> &s, const FormatSpec &spec) {
|
||||
// Check if StrChar is convertible to Char.
|
||||
internal::CharTraits<Char>::convert(StrChar());
|
||||
if (spec.type_ && spec.type_ != 's')
|
||||
@ -2921,7 +2925,8 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) {
|
||||
|
||||
BasicStringRef<Char> str(&buffer[0], format_buf.size());
|
||||
typedef internal::MakeValue< BasicFormatter<Char> > MakeValue;
|
||||
internal::Arg arg = MakeValue(str);
|
||||
internal::Arg arg;
|
||||
arg.value = MakeValue(str);
|
||||
arg.type = static_cast<internal::Arg::Type>(MakeValue::type(str));
|
||||
format_str = f.format(format_str, arg);
|
||||
}
|
||||
@ -3462,7 +3467,7 @@ const Char *BasicFormatter<Char>::format(
|
||||
FormatSpec spec;
|
||||
if (*s == ':') {
|
||||
if (arg.type == Arg::CUSTOM) {
|
||||
arg.custom.format(this, arg.custom.value, &s);
|
||||
arg.value.custom.format(this, arg.value.custom.value, &s);
|
||||
return s;
|
||||
}
|
||||
++s;
|
||||
@ -3542,20 +3547,20 @@ const Char *BasicFormatter<Char>::format(
|
||||
ULongLong value = 0;
|
||||
switch (width_arg.type) {
|
||||
case Arg::INT:
|
||||
if (width_arg.int_value < 0)
|
||||
if (width_arg.value.int_value < 0)
|
||||
FMT_THROW(FormatError("negative width"));
|
||||
value = width_arg.int_value;
|
||||
value = width_arg.value.int_value;
|
||||
break;
|
||||
case Arg::UINT:
|
||||
value = width_arg.uint_value;
|
||||
value = width_arg.value.uint_value;
|
||||
break;
|
||||
case Arg::LONG_LONG:
|
||||
if (width_arg.long_long_value < 0)
|
||||
if (width_arg.value.long_long_value < 0)
|
||||
FMT_THROW(FormatError("negative width"));
|
||||
value = width_arg.long_long_value;
|
||||
value = width_arg.value.long_long_value;
|
||||
break;
|
||||
case Arg::ULONG_LONG:
|
||||
value = width_arg.ulong_long_value;
|
||||
value = width_arg.value.ulong_long_value;
|
||||
break;
|
||||
default:
|
||||
FMT_THROW(FormatError("width is not integer"));
|
||||
@ -3580,20 +3585,20 @@ const Char *BasicFormatter<Char>::format(
|
||||
ULongLong value = 0;
|
||||
switch (precision_arg.type) {
|
||||
case Arg::INT:
|
||||
if (precision_arg.int_value < 0)
|
||||
if (precision_arg.value.int_value < 0)
|
||||
FMT_THROW(FormatError("negative precision"));
|
||||
value = precision_arg.int_value;
|
||||
value = precision_arg.value.int_value;
|
||||
break;
|
||||
case Arg::UINT:
|
||||
value = precision_arg.uint_value;
|
||||
value = precision_arg.value.uint_value;
|
||||
break;
|
||||
case Arg::LONG_LONG:
|
||||
if (precision_arg.long_long_value < 0)
|
||||
if (precision_arg.value.long_long_value < 0)
|
||||
FMT_THROW(FormatError("negative precision"));
|
||||
value = precision_arg.long_long_value;
|
||||
value = precision_arg.value.long_long_value;
|
||||
break;
|
||||
case Arg::ULONG_LONG:
|
||||
value = precision_arg.ulong_long_value;
|
||||
value = precision_arg.value.ulong_long_value;
|
||||
break;
|
||||
default:
|
||||
FMT_THROW(FormatError("precision is not integer"));
|
||||
|
||||
@ -42,7 +42,7 @@ TEST(FormatTest, ArgConverter) {
|
||||
using fmt::internal::Arg;
|
||||
Arg arg = Arg();
|
||||
arg.type = Arg::LONG_LONG;
|
||||
arg.long_long_value = std::numeric_limits<fmt::LongLong>::max();
|
||||
arg.value.long_long_value = std::numeric_limits<fmt::LongLong>::max();
|
||||
fmt::ArgConverter<fmt::LongLong>(arg, 'd').visit(arg);
|
||||
EXPECT_EQ(Arg::LONG_LONG, arg.type);
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ int result;
|
||||
void func(const char *format, const fmt::ArgList &args) { \
|
||||
result = 0; \
|
||||
for (unsigned i = 0; args[i].type; ++i) \
|
||||
result += args[i].int_value; \
|
||||
result += args[i].value.int_value; \
|
||||
}
|
||||
|
||||
MAKE_TEST(test_func)
|
||||
@ -101,7 +101,7 @@ struct S {};
|
||||
int test_variadic(FMT_GEN(10, GET_TYPE), const fmt::ArgList &args) { \
|
||||
int result = 0; \
|
||||
for (unsigned i = 0; args[i].type; ++i) \
|
||||
result += args[i].int_value; \
|
||||
result += args[i].value.int_value; \
|
||||
return result;
|
||||
}
|
||||
FMT_VARIADIC(int, test_variadic,
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
|
||||
using fmt::StringRef;
|
||||
using fmt::internal::Arg;
|
||||
using fmt::internal::Value;
|
||||
using fmt::Buffer;
|
||||
using fmt::internal::MemoryBuffer;
|
||||
|
||||
@ -70,7 +71,8 @@ std::basic_ostream<Char> &operator<<(std::basic_ostream<Char> &os, Test) {
|
||||
template <typename Char, typename T>
|
||||
Arg make_arg(const T &value) {
|
||||
typedef fmt::internal::MakeValue< fmt::BasicFormatter<Char> > MakeValue;
|
||||
Arg arg = MakeValue(value);
|
||||
Arg arg;
|
||||
arg.value = MakeValue(value);
|
||||
arg.type = static_cast<Arg::Type>(MakeValue::type(value));
|
||||
return arg;
|
||||
}
|
||||
@ -409,7 +411,7 @@ struct ArgInfo;
|
||||
#define ARG_INFO(type_code, Type, field) \
|
||||
template <> \
|
||||
struct ArgInfo<Arg::type_code> { \
|
||||
static Type get(const Arg &arg) { return arg.field; } \
|
||||
static Type get(const Arg &arg) { return arg.value.field; } \
|
||||
};
|
||||
|
||||
ARG_INFO(INT, int, int_value);
|
||||
@ -424,12 +426,12 @@ ARG_INFO(CSTRING, const char *, string.value);
|
||||
ARG_INFO(STRING, const char *, string.value);
|
||||
ARG_INFO(WSTRING, const wchar_t *, wstring.value);
|
||||
ARG_INFO(POINTER, const void *, pointer);
|
||||
ARG_INFO(CUSTOM, Arg::CustomValue, custom);
|
||||
ARG_INFO(CUSTOM, Value::CustomValue, custom);
|
||||
|
||||
#define CHECK_ARG_INFO(Type, field, value) { \
|
||||
#define CHECK_ARG_INFO(Type, field, x) { \
|
||||
Arg arg = Arg(); \
|
||||
arg.field = value; \
|
||||
EXPECT_EQ(value, ArgInfo<Arg::Type>::get(arg)); \
|
||||
arg.value.field = x; \
|
||||
EXPECT_EQ(x, ArgInfo<Arg::Type>::get(arg)); \
|
||||
}
|
||||
|
||||
TEST(ArgTest, ArgInfo) {
|
||||
@ -447,7 +449,7 @@ TEST(ArgTest, ArgInfo) {
|
||||
int p = 0;
|
||||
CHECK_ARG_INFO(POINTER, pointer, &p);
|
||||
Arg arg = Arg();
|
||||
arg.custom.value = &p;
|
||||
arg.value.custom.value = &p;
|
||||
EXPECT_EQ(&p, ArgInfo<Arg::CUSTOM>::get(arg).value);
|
||||
}
|
||||
|
||||
@ -562,11 +564,11 @@ TEST(ArgTest, MakeArg) {
|
||||
::Test t;
|
||||
Arg arg = make_arg<char>(t);
|
||||
EXPECT_EQ(fmt::internal::Arg::CUSTOM, arg.type);
|
||||
EXPECT_EQ(&t, arg.custom.value);
|
||||
EXPECT_EQ(&t, arg.value.custom.value);
|
||||
fmt::MemoryWriter w;
|
||||
fmt::BasicFormatter<char> formatter(fmt::ArgList(), w);
|
||||
const char *s = "}";
|
||||
arg.custom.format(&formatter, &t, &s);
|
||||
arg.value.custom.format(&formatter, &t, &s);
|
||||
EXPECT_EQ("test", w.str());
|
||||
}
|
||||
|
||||
@ -585,10 +587,11 @@ void format(CustomFormatter &, const char *&s, const Test &) {
|
||||
|
||||
TEST(UtilTest, MakeValueWithCustomFormatter) {
|
||||
::Test t;
|
||||
Arg arg = fmt::internal::MakeValue<CustomFormatter>(t);
|
||||
Arg arg;
|
||||
arg.value = fmt::internal::MakeValue<CustomFormatter>(t);
|
||||
CustomFormatter formatter;
|
||||
const char *s = "";
|
||||
arg.custom.format(&formatter, &t, &s);
|
||||
arg.value.custom.format(&formatter, &t, &s);
|
||||
EXPECT_STREQ("custom_format", s);
|
||||
}
|
||||
|
||||
@ -611,10 +614,10 @@ struct TestVisitor : fmt::internal::ArgVisitor<TestVisitor, Result> {
|
||||
Result visit_long_double(long double value) { return value; }
|
||||
Result visit_char(int value) { return static_cast<char>(value); }
|
||||
Result visit_cstring(const char *s) { return s; }
|
||||
Result visit_string(Arg::StringValue<char> s) { return s.value; }
|
||||
Result visit_wstring(Arg::StringValue<wchar_t> s) { return s.value; }
|
||||
Result visit_string(Value::StringValue<char> s) { return s.value; }
|
||||
Result visit_wstring(Value::StringValue<wchar_t> s) { return s.value; }
|
||||
Result visit_pointer(const void *p) { return p; }
|
||||
Result visit_custom(Arg::CustomValue c) {
|
||||
Result visit_custom(Value::CustomValue c) {
|
||||
return *static_cast<const ::Test*>(c.value);
|
||||
}
|
||||
};
|
||||
@ -648,7 +651,7 @@ TEST(ArgVisitorTest, VisitAll) {
|
||||
::Test t;
|
||||
Result result = TestVisitor().visit(make_arg<char>(t));
|
||||
EXPECT_EQ(Arg::CUSTOM, result.arg.type);
|
||||
EXPECT_EQ(&t, result.arg.custom.value);
|
||||
EXPECT_EQ(&t, result.arg.value.custom.value);
|
||||
}
|
||||
|
||||
struct TestAnyVisitor : fmt::internal::ArgVisitor<TestAnyVisitor, Result> {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user