Fix MSVC 2013 build

This commit is contained in:
Victor Zverovich 2018-07-04 11:36:38 -07:00
parent ec218a3ad1
commit e928b6724c
3 changed files with 59 additions and 73 deletions

View File

@ -948,10 +948,10 @@ struct get_type {
};
template <typename Context>
FMT_CONSTEXPR uint64_t get_types() { return 0; }
FMT_CONSTEXPR unsigned long long get_types() { return 0; }
template <typename Context, typename Arg, typename... Args>
FMT_CONSTEXPR uint64_t get_types() {
FMT_CONSTEXPR unsigned long long get_types() {
return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);
}
@ -995,27 +995,32 @@ class format_arg_store {
internal::value<Context>, basic_format_arg<Context>>::type value_type;
// If the arguments are not packed, add one more element to mark the end.
value_type data_[NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1)];
static const size_t DATA_SIZE =
NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1);
value_type data_[DATA_SIZE];
friend class basic_format_args<Context>;
static FMT_CONSTEXPR int64_t get_types() {
static FMT_CONSTEXPR long long get_types() {
return IS_PACKED ?
static_cast<int64_t>(internal::get_types<Context, Args...>()) :
-static_cast<int64_t>(NUM_ARGS);
static_cast<long long>(internal::get_types<Context, Args...>()) :
-static_cast<long long>(NUM_ARGS);
}
public:
#if FMT_USE_CONSTEXPR
static constexpr int64_t TYPES = get_types();
static constexpr long long TYPES = get_types();
#else
static const int64_t TYPES;
static const long long TYPES;
#endif
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405
// Workaround an array initialization bug in gcc 4.5 and earlier.
#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \
(FMT_MSC_VER && FMT_MSC_VER <= 1800)
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
format_arg_store(const Args &... args) {
data_ = {internal::make_arg<IS_PACKED, Context>(args)...};
value_type init[DATA_SIZE] =
{internal::make_arg<IS_PACKED, Context>(args)...};
std::memcpy(data_, init, sizeof(init));
}
#else
format_arg_store(const Args &... args)
@ -1025,7 +1030,7 @@ class format_arg_store {
#if !FMT_USE_CONSTEXPR
template <typename Context, typename ...Args>
const int64_t format_arg_store<Context, Args...>::TYPES = get_types();
const long long format_arg_store<Context, Args...>::TYPES = get_types();
#endif
/**
@ -1057,7 +1062,7 @@ class basic_format_args {
private:
// To reduce compiled code size per formatting function call, types of first
// max_packed_args arguments are passed in the types_ field.
uint64_t types_;
unsigned long long types_;
union {
// If the number of arguments is less than max_packed_args, the argument
// values are stored in values_, otherwise they are stored in args_.
@ -1070,7 +1075,7 @@ class basic_format_args {
typename internal::type type(unsigned index) const {
unsigned shift = index * 4;
uint64_t mask = 0xf;
unsigned long long mask = 0xf;
return static_cast<typename internal::type>(
(types_ & (mask << shift)) >> shift);
}
@ -1081,9 +1086,9 @@ class basic_format_args {
void set_data(const format_arg *args) { args_ = args; }
format_arg do_get(size_type index) const {
int64_t signed_types = static_cast<int64_t>(types_);
long long signed_types = static_cast<long long>(types_);
if (signed_types < 0) {
uint64_t num_args = static_cast<uint64_t>(-signed_types);
unsigned long long num_args = static_cast<unsigned long long>(-signed_types);
return index < num_args ? args_[index] : format_arg();
}
format_arg arg;
@ -1119,10 +1124,10 @@ class basic_format_args {
}
unsigned max_size() const {
int64_t signed_types = static_cast<int64_t>(types_);
long long signed_types = static_cast<long long>(types_);
return static_cast<unsigned>(
signed_types < 0 ?
-signed_types : static_cast<int64_t>(internal::max_packed_args));
-signed_types : static_cast<long long>(internal::max_packed_args));
}
};

View File

@ -1293,28 +1293,6 @@ struct align_spec : empty_spec {
// Format specifiers.
template <typename Char>
class basic_format_specs : public align_spec {
private:
template <typename FillChar>
typename std::enable_if<std::is_same<FillChar, Char>::value ||
std::is_same<FillChar, char>::value, void>::type
set(fill_spec<FillChar> fill) {
fill_ = fill.value();
}
void set(width_spec width) {
width_ = width.value();
}
void set(type_spec type) {
type_ = type.value();
}
template <typename Spec, typename... Specs>
void set(Spec spec, Specs... tail) {
set(spec);
set(tail...);
}
public:
unsigned flags_;
int precision_;
@ -1324,12 +1302,6 @@ class basic_format_specs : public align_spec {
unsigned width = 0, char type = 0, wchar_t fill = ' ')
: align_spec(width, fill), flags_(0), precision_(-1), type_(type) {}
template <typename... FormatSpecs>
explicit basic_format_specs(FormatSpecs... specs)
: align_spec(0, ' '), flags_(0), precision_(-1), type_(0) {
set(specs...);
}
FMT_CONSTEXPR bool flag(unsigned f) const { return (flags_ & f) != 0; }
FMT_CONSTEXPR int precision() const { return precision_; }
FMT_CONSTEXPR Char type() const { return type_; }
@ -1576,7 +1548,18 @@ class arg_formatter_base {
template <typename T>
typename std::enable_if<std::is_integral<T>::value, iterator>::type
operator()(T value) {
// MSVC2013 fails to compile separate overloads for bool and char_type so
// use std::is_same instead.
if (std::is_same<T, bool>::value) {
if (specs_.type_)
return (*this)(value ? 1 : 0);
write(value);
} else if (std::is_same<T, char_type>::value) {
internal::handle_char_specs(
specs_, char_spec_handler(*this, static_cast<char_type>(value)));
} else {
writer_.write_int(value, specs_);
}
return out();
}
@ -1587,13 +1570,6 @@ class arg_formatter_base {
return out();
}
iterator operator()(bool value) {
if (specs_.type_)
return (*this)(value ? 1 : 0);
write(value);
return out();
}
struct char_spec_handler : internal::error_handler {
arg_formatter_base &formatter;
char_type value;
@ -1605,11 +1581,6 @@ class arg_formatter_base {
void on_char() { formatter.write_char(value); }
};
iterator operator()(char_type value) {
internal::handle_char_specs(specs_, char_spec_handler(*this, value));
return out();
}
struct cstring_spec_handler : internal::error_handler {
arg_formatter_base &formatter;
const char_type *value;

View File

@ -252,24 +252,34 @@ class printf_arg_formatter:
using base::operator();
/** Formats an argument of type ``bool``. */
iterator operator()(bool value) {
template <typename T>
typename std::enable_if<std::is_integral<T>::value, iterator>::type
operator()(T value) {
// MSVC2013 fails to compile separate overloads for bool and char_type so
// use std::is_same instead.
if (std::is_same<T, bool>::value) {
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return (*this)(value ? 1 : 0);
return base::operator()(value ? 1 : 0);
fmt_spec.type_ = 0;
this->write(value);
return this->out();
}
/** Formats a character. */
iterator operator()(char_type value) {
} else if (std::is_same<T, char_type>::value) {
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
return (*this)(static_cast<int>(value));
fmt_spec.flags_ = 0;
fmt_spec.align_ = ALIGN_RIGHT;
return base::operator()(value);
} else {
return base::operator()(value);
}
return this->out();
}
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, iterator>::type
operator()(T value) {
return base::operator()(value);
}
/** Formats a null-terminated C string. */