Merge value and MakeValue

This commit is contained in:
Victor Zverovich 2016-12-30 09:25:01 -08:00
parent acd1811c50
commit b2a0d8914a
2 changed files with 41 additions and 47 deletions

View File

@ -1017,7 +1017,7 @@ template <typename T = void>
struct Null {};
// A helper class template to enable or disable overloads taking wide
// characters and strings in MakeValue.
// characters and strings in value's constructor.
template <typename T, typename Char>
struct WCharHelper {
typedef Null<T> Supported;
@ -1097,25 +1097,6 @@ struct CustomValue {
FormatFunc format;
};
// A formatting argument value.
template <typename Context>
struct value {
union {
int int_value;
unsigned uint_value;
LongLong long_long_value;
ULongLong ulong_long_value;
double double_value;
long double long_double_value;
const void *pointer;
StringValue<char> string;
StringValue<signed char> sstring;
StringValue<unsigned char> ustring;
StringValue<typename Context::char_type> tstring;
CustomValue<typename Context::char_type> custom;
};
};
template <typename Char>
struct NamedArg;
@ -1175,10 +1156,25 @@ template <> constexpr Type gettype<const void *>() { return POINTER; }
template <typename T>
constexpr Type type() { return gettype<typename std::decay<T>::type>(); }
// Makes a format_arg object from any type.
// A formatting argument value.
template <typename Context>
class MakeValue : public value<Context> {
class value {
public:
union {
int int_value;
unsigned uint_value;
LongLong long_long_value;
ULongLong ulong_long_value;
double double_value;
long double long_double_value;
const void *pointer;
StringValue<char> string;
StringValue<signed char> sstring;
StringValue<unsigned char> ustring;
StringValue<typename Context::char_type> tstring;
CustomValue<typename Context::char_type> custom;
};
typedef typename Context::char_type Char;
private:
@ -1188,21 +1184,21 @@ class MakeValue : public value<Context> {
// of "[const] volatile char *" which is printed as bool by iostreams.
// Do not implement!
template <typename T>
MakeValue(const T *value);
value(const T *value);
template <typename T>
MakeValue(T *value);
value(T *value);
// The following methods are private to disallow formatting of wide
// characters and strings into narrow strings as in
// fmt::format("{}", L"test");
// To fix this, use a wide format string: fmt::format(L"{}", L"test").
#if !FMT_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
MakeValue(typename WCharHelper<wchar_t, Char>::Unsupported);
value(typename WCharHelper<wchar_t, Char>::Unsupported);
#endif
MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
MakeValue(typename WCharHelper<const wchar_t *, Char>::Unsupported);
MakeValue(typename WCharHelper<const std::wstring &, Char>::Unsupported);
MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
value(typename WCharHelper<wchar_t *, Char>::Unsupported);
value(typename WCharHelper<const wchar_t *, Char>::Unsupported);
value(typename WCharHelper<const std::wstring &, Char>::Unsupported);
value(typename WCharHelper<WStringRef, Char>::Unsupported);
void set_string(StringRef str) {
this->string.value = str.data();
@ -1223,10 +1219,10 @@ class MakeValue : public value<Context> {
}
public:
MakeValue() {}
value() {}
#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
MakeValue(Type value) { \
value(Type value) { \
static_assert(internal::type<Type>() == internal::TYPE, "invalid type"); \
this->field = rhs; \
}
@ -1240,7 +1236,7 @@ class MakeValue : public value<Context> {
FMT_MAKE_VALUE(int, int_value, INT)
FMT_MAKE_VALUE(unsigned, uint_value, UINT)
MakeValue(long value) {
value(long value) {
// To minimize the number of types we need to deal with, long is
// translated either to int or to long long depending on its size.
if (const_check(sizeof(long) == sizeof(int)))
@ -1249,7 +1245,7 @@ class MakeValue : public value<Context> {
this->long_long_value = value;
}
MakeValue(unsigned long value) {
value(unsigned long value) {
if (const_check(sizeof(unsigned long) == sizeof(unsigned)))
this->uint_value = static_cast<unsigned>(value);
else
@ -1267,14 +1263,14 @@ class MakeValue : public value<Context> {
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
typedef typename WCharHelper<wchar_t, Char>::Supported WChar;
MakeValue(WChar value) {
value(WChar value) {
static_assert(internal::type<WChar>() == internal::CHAR, "invalid type");
this->int_value = value;
}
#endif
#define FMT_MAKE_STR_VALUE(Type, TYPE) \
MakeValue(Type value) { \
value(Type value) { \
static_assert(internal::type<Type>() == internal::TYPE, "invalid type"); \
set_string(value); \
}
@ -1290,8 +1286,8 @@ class MakeValue : public value<Context> {
FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \
MakeValue(typename WCharHelper<Type, Char>::Supported value) { \
static_assert(internal::type<Type>() == internal::TYPE, "invalid type"); \
value(typename WCharHelper<Type, Char>::Supported value) { \
static_assert(internal::type<Type>() == internal::TYPE, "invalid type"); \
set_string(value); \
}
@ -1304,17 +1300,16 @@ class MakeValue : public value<Context> {
FMT_MAKE_VALUE(const void *, pointer, POINTER)
template <typename T>
MakeValue(const T &value,
typename EnableIf<Not<
ConvertToInt<T>::value>::value, int>::type = 0) {
value(const T &value,
typename EnableIf<Not<ConvertToInt<T>::value>::value, int>::type = 0) {
static_assert(internal::type<T>() == internal::CUSTOM, "invalid type");
this->custom.value = &value;
this->custom.format = &format_custom_arg<T>;
}
template <typename T>
MakeValue(const T &value,
typename EnableIf<ConvertToInt<T>::value, int>::type = 0) {
value(const T &value,
typename EnableIf<ConvertToInt<T>::value, int>::type = 0) {
static_assert(internal::type<T>() == internal::INT, "invalid type");
this->int_value = value;
}
@ -1322,7 +1317,7 @@ class MakeValue : public value<Context> {
// Additional template param `Char_` is needed here because make_type always
// uses char.
template <typename Char_>
MakeValue(const NamedArg<Char_> &value) {
value(const NamedArg<Char_> &value) {
static_assert(
internal::type<const NamedArg<Char_> &>() == internal::NAMED_ARG,
"invalid type");
@ -1437,7 +1432,7 @@ template <typename Context, typename T>
basic_format_arg<Context> make_arg(const T &value) {
basic_format_arg<Context> arg;
arg.type_ = internal::type<T>();
arg.value_ = internal::MakeValue<Context>(value);
arg.value_ = value;
return arg;
}
@ -1516,7 +1511,7 @@ enum { MAX_PACKED_ARGS = 16 };
template <bool IS_PACKED, typename Context, typename T>
inline typename std::enable_if<IS_PACKED, value<Context>>::type
make_arg(const T& value) {
return MakeValue<Context>(value);
return value;
}
template <bool IS_PACKED, typename Context, typename T>

View File

@ -423,8 +423,7 @@ void format_value(fmt::Writer &, const Test &, CustomContext &ctx) {
TEST(UtilTest, MakeValueWithCustomFormatter) {
::Test t;
fmt::internal::value<CustomContext> arg =
fmt::internal::MakeValue<CustomContext>(t);
fmt::internal::value<CustomContext> arg(t);
CustomContext ctx = {false};
fmt::MemoryWriter w;
arg.custom.format(w, &t, &ctx);