diff --git a/include/fmt/core.h b/include/fmt/core.h index f8dc5755..58d0e7bb 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -170,8 +170,10 @@ namespace fmt { // An implementation of declval for pre-C++11 compilers such as gcc 4. +namespace internal { template typename std::add_rvalue_reference::type declval() FMT_NOEXCEPT; +} /** \rst @@ -962,8 +964,15 @@ class arg_store { public: static const uint64_t TYPES; +#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405 && !defined(__clang__) + // Workaround an array initialization bug in gcc 4.5 and earlier. + arg_store(const Args &... args) { + data_ = {internal::make_arg(args)...}; + } +#else arg_store(const Args &... args) : data_{internal::make_arg(args)...} {} +#endif basic_format_args operator*() const { return *this; } diff --git a/include/fmt/format.h b/include/fmt/format.h index e72dcd1e..5e771bcf 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -212,6 +212,19 @@ inline uint32_t clzll(uint64_t x) { namespace fmt { namespace internal { + +// An implementation of begin and end for pre-C++11 compilers such as gcc 4. +template +FMT_CONSTEXPR auto begin(const C &c) -> decltype(c.begin()) { + return c.begin(); +} +template +FMT_CONSTEXPR T *begin(T (&array)[N]) FMT_NOEXCEPT { return array; } +template +FMT_CONSTEXPR auto end(const C &c) -> decltype(c.end()) { return c.end(); } +template +FMT_CONSTEXPR T *end(T (&array)[N]) FMT_NOEXCEPT { return array + N; } + struct dummy_int { int data[2]; operator int() const { return 0; } @@ -2093,7 +2106,7 @@ template class arg_formatter: public internal::arg_formatter_base { private: typedef typename Range::value_type char_type; - typedef decltype(declval().begin()) iterator; + typedef decltype(internal::declval().begin()) iterator; typedef internal::arg_formatter_base base; typedef basic_context context_type; @@ -2191,7 +2204,7 @@ template class basic_writer { public: typedef typename Range::value_type char_type; - typedef decltype(declval().begin()) iterator; + typedef decltype(internal::declval().begin()) iterator; typedef basic_format_specs format_specs; private: @@ -2660,10 +2673,15 @@ void basic_writer::write_double(T value, const format_specs &spec) { sign = spec.flag(PLUS_FLAG) ? '+' : ' '; } - auto write_inf_or_nan = [this, &spec, sign](const char *str) { - this->write_padded(INF_SIZE + (sign ? 1 : 0), spec, - inf_or_nan_writer{sign, str}); - }; + struct write_inf_or_nan_t { + basic_writer &writer; + format_specs spec; + char sign; + void operator()(const char *str) const { + writer.write_padded(INF_SIZE + (sign ? 1 : 0), spec, + inf_or_nan_writer{sign, str}); + } + } write_inf_or_nan = {*this, spec, sign}; // Format NaN and ininity ourselves because sprintf's output is not consistent // across platforms. @@ -3235,14 +3253,14 @@ arg_join join(It begin, It end, wstring_view sep) { #if FMT_USE_TRAILING_RETURN template auto join(const Range &range, string_view sep) - -> arg_join { - return join(std::begin(range), std::end(range), sep); + -> arg_join { + return join(internal::begin(range), internal::end(range), sep); } template auto join(const Range &range, wstring_view sep) - -> arg_join { - return join(std::begin(range), std::end(range), sep); + -> arg_join { + return join(internal::begin(range), internal::end(range), sep); } #endif