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