diff --git a/fmt/format.h b/fmt/format.h index 0cd9e8b9..e268eb16 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -156,6 +156,15 @@ typedef __int64 intmax_t; # include // for std::move #endif +#ifndef FMT_HAS_THREAD_LOCAL +// Thread local storage are available in GCC since version 4.8 +// (https://gcc.gnu.org/projects/cxx-status.html) and in Visual C++ +// since version 2015. +# define FMT_HAS_THREAD_LOCAL \ + (FMT_HAS_FEATURE(cxx_thread_local) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) +#endif + // Check if exceptions are disabled. #if defined(__GNUC__) && !defined(__EXCEPTIONS) # define FMT_EXCEPTIONS 0 @@ -1427,7 +1436,10 @@ class ArgList { return args_[index]; } +#if FMT_HAS_THREAD_LOCAL + // Cross-thread serialization facility + template void serialize(std::vector& buffer) const; template @@ -1440,8 +1452,11 @@ private: static void serialize_extra_data(uint8_t*& data_buffer, const internal::Arg& arg); template static void deserialize_extra_data(uint8_t*& data_buffer, internal::Arg& arg); +#endif }; +#if FMT_HAS_THREAD_LOCAL + // Cross-thread serialization facility template @@ -1658,6 +1673,8 @@ inline ArgList ArgList::deserialize(std::vector& buffer) return args_list; } +#endif + #define FMT_DISPATCH(call) static_cast(this)->call /** diff --git a/test/format-test.cc b/test/format-test.cc index 050ce6d6..491df150 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1654,6 +1654,8 @@ TEST(FormatTest, CustomArgFormatter) { custom_format("{}", 42); } +#if FMT_HAS_THREAD_LOCAL + std::string serialize_deserialize(const char *format_str, fmt::ArgList args) { std::vector buffer; args.serialize(buffer); @@ -1681,3 +1683,5 @@ TEST(FormatTest, Serialization) { EXPECT_EQ(serialize_deserialize("Elapsed time: {s:.2f} seconds", "s"_a = 1.23), "Elapsed time: 1.23 seconds"); EXPECT_EQ(serialize_deserialize("The answer is {}"_format(42).c_str()), "The answer is 42"); } + +#endif