diff --git a/fmt/format.h b/fmt/format.h index 7ca1de9b..4093f3ea 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -2093,34 +2094,33 @@ inline uint64_t make_type(const T &arg) { return MakeValue< BasicFormatter >::type(arg); } -template -struct ArgArray; +template +class format_arg_store { + private: + static const size_t NUM_ARGS = sizeof...(Args); + static const bool PACKED = NUM_ARGS <= format_args::MAX_PACKED_ARGS; -template -struct ArgArray { - typedef Value Type[N > 0 ? N : 1]; + typedef typename std::conditional::type value_type; - template - static Value make(const T &value) { -#ifdef __clang__ - Value result = MakeValue(value); - // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang: - // https://github.com/fmtlib/fmt/issues/276 - (void)result.custom.format; - return result; -#else - return MakeValue(value); -#endif - } + // If the arguments are not packed we add one more element to mark the end. + std::array data_; + + template + friend format_arg_store make_format_args(const A & ... args); + + public: + template + format_arg_store(const Args &... args, Formatter *) + : data_{MakeValue(args)...} {} + + const value_type *data() const { return data_.data(); } }; -template -struct ArgArray { - typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE - - template - static Arg make(const T &value) { return MakeArg(value); } -}; +template +inline format_arg_store make_format_args(const Args & ... args) { + Formatter *f = nullptr; + return format_arg_store(args..., f); +} template inline uint64_t make_type(const Arg &first, const Args & ... tail) { @@ -2140,20 +2140,16 @@ inline uint64_t make_type(const Arg &first, const Args & ... tail) { # define FMT_VARIADIC_VOID(func, arg_type) \ template \ void func(arg_type arg0, const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - func(arg0, fmt::format_args(fmt::internal::make_type(args...), array)); \ + auto store = fmt::internal::make_format_args< fmt::BasicFormatter >(args...); \ + func(arg0, fmt::format_args(fmt::internal::make_type(args...), store.data())); \ } // Defines a variadic constructor. # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ template \ ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ - func(arg0, arg1, fmt::format_args(fmt::internal::make_type(args...), array)); \ + auto store = internal::make_format_args< fmt::BasicFormatter >(args...); \ + func(arg0, arg1, fmt::format_args(fmt::internal::make_type(args...), store.data())); \ } // Generates a comma-separated list with results of applying f to pairs @@ -3290,11 +3286,9 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; template \ ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ const Args & ... args) { \ - typedef fmt::internal::ArgArray ArgArray; \ - typename ArgArray::Type array{ \ - ArgArray::template make >(args)...}; \ + auto store = fmt::internal::make_format_args< fmt::BasicFormatter >(args...); \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ - fmt::format_args(fmt::internal::make_type(args...), array)); \ + fmt::format_args(fmt::internal::make_type(args...), store.data())); \ } /** diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 86e72b97..95ddca55 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -121,6 +121,7 @@ endif () check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG) if (HAVE_FNO_EXCEPTIONS_FLAG) add_library(noexception-test ../fmt/format.cc) + target_compile_options(noexception-test PUBLIC ${CPP11_FLAG}) target_include_directories(noexception-test PRIVATE ${PROJECT_SOURCE_DIR}) target_compile_options(noexception-test PRIVATE -fno-exceptions) endif ()