mirror of
https://github.com/fmtlib/fmt.git
synced 2026-04-29 10:13:37 +02:00
Add more compilers to CI and increase FMT_PEDANTIC warning levels (#736)
* Add a _lot_ more warnings to FMT_PEDANTIC Fix these warnings * Add more compilers to CI Fix (some) of the compiler errors with them * Enable -Werror on CI Increase warning level on MSVC when compiling with FMT_PEDANTIC * Add VS 2013 and 2015 to Appveyor * Fix Appveyor tests Formatting * Implement requested changes Fix some of the MSVC warnings Implement C++11 integer_sequence * Reintroduce appveyor-build.py * Remove ranges-test from tests * Remove (some) explicit warning suppressions Fix C++ standard setting in CI * Remove (some) explicit warning suppressions Fix C++ standard setting in CI * Fix test builds with C++11 * Enable pedantic warnings on tests * Fix warnings from edits to master * Cleanups * Add C++11 support to ranges.h Re-enable ranges-test Fix a Visual Studio error about function not returning a value in printf.h Fix a bug in .travis.yml
This commit is contained in:
committed by
Victor Zverovich
parent
dd1a5ef7f9
commit
691a7a91a1
+29
-12
@@ -30,6 +30,12 @@
|
||||
# define FMT_HAS_INCLUDE(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __has_cpp_attribute
|
||||
# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
|
||||
#else
|
||||
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
#else
|
||||
@@ -95,6 +101,12 @@
|
||||
# define FMT_USE_NULLPTR 0
|
||||
#endif
|
||||
|
||||
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
|
||||
# define FMT_NORETURN [[noreturn]]
|
||||
#else
|
||||
# define FMT_NORETURN /*noreturn*/
|
||||
#endif
|
||||
|
||||
// Check if exceptions are disabled.
|
||||
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
|
||||
# define FMT_EXCEPTIONS 0
|
||||
@@ -218,7 +230,7 @@ class basic_string_view {
|
||||
#else
|
||||
struct type {
|
||||
const char *data() const { return FMT_NULL; }
|
||||
size_t size() const { return 0; };
|
||||
size_t size() const { return 0; }
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -550,11 +562,17 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value);
|
||||
return static_cast<ValueType>(val); \
|
||||
}
|
||||
|
||||
#define FMT_MAKE_VALUE_SAME(TAG, Type) \
|
||||
template <typename C> \
|
||||
FMT_CONSTEXPR typed_value<C, TAG> make_value(Type val) { \
|
||||
return val; \
|
||||
}
|
||||
|
||||
FMT_MAKE_VALUE(bool_type, bool, int)
|
||||
FMT_MAKE_VALUE(int_type, short, int)
|
||||
FMT_MAKE_VALUE(uint_type, unsigned short, unsigned)
|
||||
FMT_MAKE_VALUE(int_type, int, int)
|
||||
FMT_MAKE_VALUE(uint_type, unsigned, unsigned)
|
||||
FMT_MAKE_VALUE_SAME(int_type, int)
|
||||
FMT_MAKE_VALUE_SAME(uint_type, unsigned)
|
||||
|
||||
// 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.
|
||||
@@ -568,8 +586,8 @@ FMT_MAKE_VALUE(
|
||||
(sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type),
|
||||
unsigned long, ulong_type)
|
||||
|
||||
FMT_MAKE_VALUE(long_long_type, long long, long long)
|
||||
FMT_MAKE_VALUE(ulong_long_type, unsigned long long, unsigned long long)
|
||||
FMT_MAKE_VALUE_SAME(long_long_type, long long)
|
||||
FMT_MAKE_VALUE_SAME(ulong_long_type, unsigned long long)
|
||||
FMT_MAKE_VALUE(int_type, signed char, int)
|
||||
FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
|
||||
FMT_MAKE_VALUE(char_type, char, int)
|
||||
@@ -583,8 +601,8 @@ inline typed_value<C, char_type> make_value(wchar_t val) {
|
||||
#endif
|
||||
|
||||
FMT_MAKE_VALUE(double_type, float, double)
|
||||
FMT_MAKE_VALUE(double_type, double, double)
|
||||
FMT_MAKE_VALUE(long_double_type, long double, long double)
|
||||
FMT_MAKE_VALUE_SAME(double_type, double)
|
||||
FMT_MAKE_VALUE_SAME(long_double_type, long double)
|
||||
|
||||
// Formatting of wide strings into a narrow buffer and multibyte strings
|
||||
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
|
||||
@@ -594,18 +612,17 @@ FMT_MAKE_VALUE(cstring_type, const typename C::char_type*,
|
||||
const typename C::char_type*)
|
||||
|
||||
FMT_MAKE_VALUE(cstring_type, signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE(cstring_type, const signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE_SAME(cstring_type, const signed char*)
|
||||
FMT_MAKE_VALUE(cstring_type, unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(cstring_type, const unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(string_type, basic_string_view<typename C::char_type>,
|
||||
basic_string_view<typename C::char_type>)
|
||||
FMT_MAKE_VALUE_SAME(cstring_type, const unsigned char*)
|
||||
FMT_MAKE_VALUE_SAME(string_type, basic_string_view<typename C::char_type>)
|
||||
FMT_MAKE_VALUE(string_type,
|
||||
typename basic_string_view<typename C::char_type>::type,
|
||||
basic_string_view<typename C::char_type>)
|
||||
FMT_MAKE_VALUE(string_type, const std::basic_string<typename C::char_type>&,
|
||||
basic_string_view<typename C::char_type>)
|
||||
FMT_MAKE_VALUE(pointer_type, void*, const void*)
|
||||
FMT_MAKE_VALUE(pointer_type, const void*, const void*)
|
||||
FMT_MAKE_VALUE_SAME(pointer_type, const void*)
|
||||
|
||||
#if FMT_USE_NULLPTR
|
||||
FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*)
|
||||
|
||||
@@ -45,12 +45,6 @@
|
||||
# define FMT_CATCH(x) if (false)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Disable the warning about declaration shadowing because it affects too
|
||||
// many valid cases.
|
||||
# pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
@@ -71,9 +65,6 @@ inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
FMT_FUNC format_error::~format_error() throw() {}
|
||||
FMT_FUNC system_error::~system_error() FMT_DTOR_NOEXCEPT {}
|
||||
|
||||
namespace {
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
+63
-61
@@ -37,6 +37,33 @@
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __clang__
|
||||
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
||||
#else
|
||||
# define FMT_CLANG_VERSION 0
|
||||
#endif
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
# define FMT_ICC_VERSION __INTEL_COMPILER
|
||||
#elif defined(__ICL)
|
||||
# define FMT_ICC_VERSION __ICL
|
||||
#else
|
||||
# define FMT_ICC_VERSION 0
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 406) || \
|
||||
FMT_CLANG_VERSION
|
||||
# pragma GCC diagnostic push
|
||||
|
||||
// Disable the warning about declaration shadowing because it affects too
|
||||
// many valid cases.
|
||||
# pragma GCC diagnostic ignored "-Wshadow"
|
||||
|
||||
// Disable the warning about implicit conversions that may change the sign of
|
||||
// an integer; silencing it otherwise would require many explicit casts.
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef _SECURE_SCL
|
||||
@@ -55,47 +82,10 @@
|
||||
# define FMT_HAS_BUILTIN(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# if FMT_GCC_VERSION >= 406
|
||||
# pragma GCC diagnostic push
|
||||
|
||||
// Disable the warning about declaration shadowing because it affects too
|
||||
// many valid cases.
|
||||
# pragma GCC diagnostic ignored "-Wshadow"
|
||||
|
||||
// Disable the warning about implicit conversions that may change the sign of
|
||||
// an integer; silencing it otherwise would require many explicit casts.
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
||||
#endif
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
# define FMT_ICC_VERSION __INTEL_COMPILER
|
||||
#elif defined(__ICL)
|
||||
# define FMT_ICC_VERSION __ICL
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
|
||||
# pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
|
||||
# pragma clang diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC_LIBSTD__
|
||||
# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)
|
||||
#endif
|
||||
|
||||
#ifdef __has_cpp_attribute
|
||||
# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
|
||||
#else
|
||||
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef FMT_THROW
|
||||
# if FMT_EXCEPTIONS
|
||||
# if FMT_MSC_VER
|
||||
@@ -116,7 +106,7 @@ FMT_END_NAMESPACE
|
||||
# define FMT_THROW(x) throw x
|
||||
# endif
|
||||
# else
|
||||
# define FMT_THROW(x) assert(false)
|
||||
# define FMT_THROW(x) do { static_cast<void>(sizeof(x)); assert(false); } while(false);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -124,7 +114,7 @@ FMT_END_NAMESPACE
|
||||
// For Intel's compiler both it and the system gcc/msc must support UDLs.
|
||||
# if (FMT_HAS_FEATURE(cxx_user_literals) || \
|
||||
FMT_GCC_VERSION >= 407 || FMT_MSC_VER >= 1900) && \
|
||||
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
|
||||
(!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1500)
|
||||
# define FMT_USE_USER_DEFINED_LITERALS 1
|
||||
# else
|
||||
# define FMT_USE_USER_DEFINED_LITERALS 0
|
||||
@@ -142,7 +132,8 @@ FMT_END_NAMESPACE
|
||||
#ifndef FMT_USE_EXTERN_TEMPLATES
|
||||
# ifndef FMT_HEADER_ONLY
|
||||
# define FMT_USE_EXTERN_TEMPLATES \
|
||||
(FMT_CLANG_VERSION >= 209 || (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
|
||||
((FMT_CLANG_VERSION >= 209 && __cplusplus >= 201103L) || \
|
||||
(FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
|
||||
# else
|
||||
# define FMT_USE_EXTERN_TEMPLATES 0
|
||||
# endif
|
||||
@@ -151,6 +142,14 @@ FMT_END_NAMESPACE
|
||||
#if FMT_HAS_GXX_CXX11 || FMT_HAS_FEATURE(cxx_trailing_return) || \
|
||||
FMT_MSC_VER >= 1600
|
||||
# define FMT_USE_TRAILING_RETURN 1
|
||||
#else
|
||||
# define FMT_USE_TRAILING_RETURN 0
|
||||
#endif
|
||||
|
||||
#if FMT_HAS_GXX_CXX11 || FMT_HAS_FEATURE(cxx_rvalue_references) || FMT_MSC_VER >= 1600
|
||||
# define FMT_USE_RVALUE_REFERENCES 1
|
||||
#else
|
||||
# define FMT_USE_RVALUE_REFERENCES 0
|
||||
#endif
|
||||
|
||||
#ifndef FMT_USE_GRISU
|
||||
@@ -284,18 +283,18 @@ class fp {
|
||||
typedef uint64_t significand_type;
|
||||
|
||||
// All sizes are in bits.
|
||||
static constexpr int char_size = std::numeric_limits<unsigned char>::digits;
|
||||
static FMT_CONSTEXPR_DECL const int char_size = std::numeric_limits<unsigned char>::digits;
|
||||
// Subtract 1 to account for an implicit most significant bit in the
|
||||
// normalized form.
|
||||
static constexpr int double_significand_size =
|
||||
static FMT_CONSTEXPR_DECL const int double_significand_size =
|
||||
std::numeric_limits<double>::digits - 1;
|
||||
static constexpr uint64_t implicit_bit = 1ull << double_significand_size;
|
||||
static FMT_CONSTEXPR_DECL const uint64_t implicit_bit = 1ull << double_significand_size;
|
||||
|
||||
public:
|
||||
significand_type f;
|
||||
int e;
|
||||
|
||||
static constexpr int significand_size = sizeof(significand_type) * char_size;
|
||||
static FMT_CONSTEXPR_DECL const int significand_size = sizeof(significand_type) * char_size;
|
||||
|
||||
fp(uint64_t f, int e): f(f), e(e) {}
|
||||
|
||||
@@ -318,7 +317,7 @@ class fp {
|
||||
f += implicit_bit;
|
||||
else
|
||||
biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
|
||||
e = biased_e - exponent_bias - double_significand_size;
|
||||
e = static_cast<int>(biased_e - exponent_bias - double_significand_size);
|
||||
}
|
||||
|
||||
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
|
||||
@@ -455,8 +454,6 @@ class format_error : public std::runtime_error {
|
||||
|
||||
explicit format_error(const std::string &message)
|
||||
: std::runtime_error(message) {}
|
||||
|
||||
FMT_API ~format_error() throw();
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
@@ -1673,6 +1670,13 @@ FMT_CONSTEXPR unsigned parse_nonnegative_int(Iterator &it, ErrorHandler &&eh) {
|
||||
return value;
|
||||
}
|
||||
|
||||
#if FMT_MSC_VER
|
||||
// Warns that the compiler cannot generate an assignment operator
|
||||
// The class has a reference member variable, so this is obviously the case
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4512)
|
||||
#endif
|
||||
|
||||
template <typename Char, typename Context>
|
||||
class custom_formatter: public function<bool> {
|
||||
private:
|
||||
@@ -1690,6 +1694,10 @@ class custom_formatter: public function<bool> {
|
||||
bool operator()(T) const { return false; }
|
||||
};
|
||||
|
||||
#if FMT_MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct is_integer {
|
||||
enum {
|
||||
@@ -2380,8 +2388,6 @@ class system_error : public std::runtime_error {
|
||||
init(error_code, message, make_format_args(args...));
|
||||
}
|
||||
|
||||
FMT_API ~system_error() FMT_DTOR_NOEXCEPT;
|
||||
|
||||
int error_code() const { return error_code_; }
|
||||
};
|
||||
|
||||
@@ -2650,7 +2656,7 @@ class basic_writer {
|
||||
};
|
||||
|
||||
struct double_writer {
|
||||
unsigned n;
|
||||
size_t n;
|
||||
char sign;
|
||||
basic_memory_buffer<char_type> &buffer;
|
||||
|
||||
@@ -2904,12 +2910,12 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
|
||||
internal::fp product = fp_value * dec_pow;
|
||||
// Generate output.
|
||||
internal::fp one(1ull << -product.e, product.e);
|
||||
uint32_t hi = product.f >> -one.e;
|
||||
uint64_t hi = product.f >> -one.e;
|
||||
uint64_t f = product.f & (one.f - 1);
|
||||
typedef back_insert_range<internal::basic_buffer<char_type>> range;
|
||||
basic_writer<range> w{range(buffer)};
|
||||
w.write(hi);
|
||||
unsigned digits = buffer.size();
|
||||
size_t digits = buffer.size();
|
||||
w.write('.');
|
||||
const unsigned max_digits = 18;
|
||||
while (digits++ < max_digits) {
|
||||
@@ -2924,7 +2930,7 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
|
||||
normalized_spec.type_ = handler.type;
|
||||
write_double_sprintf(value, normalized_spec, buffer);
|
||||
}
|
||||
unsigned n = buffer.size();
|
||||
size_t n = buffer.size();
|
||||
align_spec as = spec;
|
||||
if (spec.align() == ALIGN_NUMERIC) {
|
||||
if (sign) {
|
||||
@@ -3215,8 +3221,8 @@ struct formatter<
|
||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||
specs_.precision_, specs_.precision_ref, ctx);
|
||||
typedef output_range<typename FormatContext::iterator,
|
||||
typename FormatContext::char_type> range;
|
||||
visit(arg_formatter<range>(ctx, specs_),
|
||||
typename FormatContext::char_type> range_type;
|
||||
visit(arg_formatter<range_type>(ctx, specs_),
|
||||
internal::make_arg<FormatContext>(val));
|
||||
return ctx.out();
|
||||
}
|
||||
@@ -3702,7 +3708,7 @@ FMT_END_NAMESPACE
|
||||
|
||||
#define FMT_STRING(s) [] { \
|
||||
struct S : fmt::format_string { \
|
||||
static FMT_CONSTEXPR auto data() { return s; } \
|
||||
static FMT_CONSTEXPR decltype(s) data() { return s; } \
|
||||
static FMT_CONSTEXPR size_t size() { return sizeof(s); } \
|
||||
}; \
|
||||
return S{}; \
|
||||
@@ -3731,12 +3737,8 @@ FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
// Restore warnings.
|
||||
#if FMT_GCC_VERSION >= 406
|
||||
#if FMT_GCC_VERSION >= 406 || FMT_CLANG_VERSION
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // FMT_FORMAT_H_
|
||||
|
||||
@@ -52,7 +52,7 @@ class printf_precision_handler: public function<int> {
|
||||
typename std::enable_if<!std::is_integral<T>::value, int>::type
|
||||
operator()(T) {
|
||||
FMT_THROW(format_error("precision is not integer"));
|
||||
return 0;
|
||||
return 0; // Silence visual studio
|
||||
}
|
||||
};
|
||||
|
||||
@@ -194,7 +194,7 @@ class printf_width_handler: public function<unsigned> {
|
||||
typename std::enable_if<!std::is_integral<T>::value, unsigned>::type
|
||||
operator()(T) {
|
||||
FMT_THROW(format_error("width is not integer"));
|
||||
return 0;
|
||||
return 0; // Silence Visual Studio
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
@@ -635,8 +635,13 @@ inline int fprintf(std::FILE *f, string_view format_str, const Args & ... args)
|
||||
template <typename... Args>
|
||||
inline int fprintf(std::FILE *f, wstring_view format_str,
|
||||
const Args & ... args) {
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 440
|
||||
return vfprintf<wchar_t>(f, format_str,
|
||||
make_format_args<typename printf_context<internal::wbuffer>::type>(args...));
|
||||
#else
|
||||
return vfprintf(f, format_str,
|
||||
make_format_args<typename printf_context<internal::wbuffer>::type>(args...));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int vprintf(string_view format, printf_args args) {
|
||||
|
||||
+62
-29
@@ -126,18 +126,39 @@ struct is_tuple_like {
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
is_tuple_like_<T>::value && !is_range_<T>::value;
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
#if FMT_HAS_FEATURE(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
|
||||
# define FMT_USE_INTEGER_SEQUENCE 1
|
||||
// Check for integer_sequence
|
||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
|
||||
template <typename T, T... N>
|
||||
using integer_sequence = std::integer_sequence<T, N...>;
|
||||
template <std::size_t... N>
|
||||
using index_sequence = std::index_sequence<N...>;
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = std::make_index_sequence<N>;
|
||||
#else
|
||||
# define FMT_USE_INTEGER_SEQUENCE 0
|
||||
template <typename T, T... N>
|
||||
struct integer_sequence {
|
||||
typedef T value_type;
|
||||
|
||||
static FMT_CONSTEXPR std::size_t size() {
|
||||
return sizeof...(N);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t... N>
|
||||
using index_sequence = integer_sequence<std::size_t, N...>;
|
||||
|
||||
template <typename T, std::size_t N, T... Ns>
|
||||
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
|
||||
template <typename T, T... Ns>
|
||||
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
|
||||
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = make_integer_sequence<std::size_t, N>;
|
||||
#endif
|
||||
|
||||
#if FMT_USE_INTEGER_SEQUENCE
|
||||
namespace internal {
|
||||
template <size_t... Is, class Tuple, class F>
|
||||
void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
|
||||
template <class Tuple, class F, size_t... Is>
|
||||
void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
|
||||
using std::get;
|
||||
// using free function get<I>(T) now.
|
||||
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
|
||||
@@ -145,7 +166,7 @@ void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
FMT_CONSTEXPR std::make_index_sequence<std::tuple_size<T>::value>
|
||||
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value>
|
||||
get_indexes(T const &) { return {}; }
|
||||
|
||||
template <class Tuple, class F>
|
||||
@@ -157,21 +178,13 @@ void for_each(Tuple &&tup, F &&f) {
|
||||
|
||||
template <typename TupleT, typename Char>
|
||||
struct formatter<TupleT, Char,
|
||||
typename std::enable_if<fmt::internal::is_tuple_like<TupleT>::value>::type> {
|
||||
|
||||
fmt::formatting_tuple<Char> formatting;
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||
return formatting.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext = format_context>
|
||||
auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
std::size_t i = 0;
|
||||
internal::copy(formatting.prefix, out);
|
||||
internal::for_each(values, [&](const auto &v) {
|
||||
typename std::enable_if<internal::is_tuple_like<TupleT>::value>::type> {
|
||||
private:
|
||||
// C++11 generic lambda for format()
|
||||
template <typename FormatContext>
|
||||
struct format_each {
|
||||
template <typename T>
|
||||
void operator()(const T& v) {
|
||||
if (i > 0) {
|
||||
if (formatting.add_prepostfix_space) {
|
||||
*out++ = ' ';
|
||||
@@ -184,7 +197,28 @@ struct formatter<TupleT, Char,
|
||||
format_to(out, "{}", v);
|
||||
}
|
||||
++i;
|
||||
});
|
||||
}
|
||||
|
||||
formatting_tuple<Char>& formatting;
|
||||
std::size_t& i;
|
||||
typename std::add_lvalue_reference<decltype(std::declval<FormatContext>().out())>::type out;
|
||||
};
|
||||
|
||||
public:
|
||||
formatting_tuple<Char> formatting;
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||
return formatting.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext = format_context>
|
||||
auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
std::size_t i = 0;
|
||||
internal::copy(formatting.prefix, out);
|
||||
|
||||
internal::for_each(values, format_each<FormatContext>{formatting, i, out});
|
||||
if (formatting.add_prepostfix_space) {
|
||||
*out++ = ' ';
|
||||
}
|
||||
@@ -193,13 +227,12 @@ struct formatter<TupleT, Char,
|
||||
return ctx.out();
|
||||
}
|
||||
};
|
||||
#endif // FMT_USE_INTEGER_SEQUENCE
|
||||
|
||||
template <typename RangeT, typename Char>
|
||||
struct formatter< RangeT, Char,
|
||||
typename std::enable_if<fmt::internal::is_range<RangeT>::value>::type> {
|
||||
struct formatter<RangeT, Char,
|
||||
typename std::enable_if<internal::is_range<RangeT>::value>::type> {
|
||||
|
||||
fmt::formatting_range<Char> formatting;
|
||||
formatting_range<Char> formatting;
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||
|
||||
@@ -54,7 +54,6 @@ inline std::tm localtime(std::time_t time) {
|
||||
return lt.tm_;
|
||||
// Too big time values may be unsupported.
|
||||
FMT_THROW(format_error("time_t value out of range"));
|
||||
return std::tm();
|
||||
}
|
||||
|
||||
// Thread-safe replacement for std::gmtime
|
||||
@@ -90,7 +89,6 @@ inline std::tm gmtime(std::time_t time) {
|
||||
return gt.tm_;
|
||||
// Too big time values may be unsupported.
|
||||
FMT_THROW(format_error("time_t value out of range"));
|
||||
return std::tm();
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
Reference in New Issue
Block a user