mirror of
https://github.com/fmtlib/fmt.git
synced 2025-04-18 02:43:08 +00:00
Emulate variadic functions on older compilers.
This commit is contained in:
parent
2f752abe97
commit
ef34eb6ec2
152
format.h
152
format.h
@ -119,6 +119,14 @@
|
|||||||
TypeName(const TypeName&); \
|
TypeName(const TypeName&); \
|
||||||
void operator=(const TypeName&)
|
void operator=(const TypeName&)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define FMT_DEPRECATED(func) func __attribute__((deprecated))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define FMT_DEPRECATED(func) __declspec(deprecated) func
|
||||||
|
#else
|
||||||
|
# define FMT_DEPRECATED(func) func
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FMT_MSC_VER
|
#if FMT_MSC_VER
|
||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable: 4521) // 'class' : multiple copy constructors specified
|
# pragma warning(disable: 4521) // 'class' : multiple copy constructors specified
|
||||||
@ -864,34 +872,47 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generates a comma-separated list by applying f to numbers 1..n.
|
#if FMT_USE_VARIADIC_TEMPLATES
|
||||||
#define FMT_GEN(n, f) FMT_GEN##n(f)
|
// Defines a variadic function returning void.
|
||||||
#define FMT_GEN1(f) f(1)
|
# define FMT_VARIADIC_VOID(func, arg_type) \
|
||||||
#define FMT_GEN2(f) FMT_GEN1(f), f(2)
|
template<typename... Args> \
|
||||||
#define FMT_GEN3(f) FMT_GEN2(f), f(3)
|
void func(arg_type arg1, const Args & ... args) { \
|
||||||
#define FMT_GEN4(f) FMT_GEN3(f), f(4)
|
const BasicArg<> \
|
||||||
#define FMT_GEN5(f) FMT_GEN4(f), f(5)
|
arg_array[fmt::internal::NonZero<sizeof...(Args)>::VALUE] = {args...}; \
|
||||||
#define FMT_GEN6(f) FMT_GEN5(f), f(6)
|
func(arg1, ArgList(arg_array, sizeof...(Args))); \
|
||||||
#define FMT_GEN7(f) FMT_GEN6(f), f(7)
|
}
|
||||||
#define FMT_GEN8(f) FMT_GEN7(f), f(8)
|
#else
|
||||||
#define FMT_GEN9(f) FMT_GEN8(f), f(9)
|
// Generates a comma-separated list with results of applying f to numbers 1..n.
|
||||||
|
# define FMT_GEN(n, f) FMT_GEN##n(f)
|
||||||
|
# define FMT_GEN1(f) f(1)
|
||||||
|
# define FMT_GEN2(f) FMT_GEN1(f), f(2)
|
||||||
|
# define FMT_GEN3(f) FMT_GEN2(f), f(3)
|
||||||
|
# define FMT_GEN4(f) FMT_GEN3(f), f(4)
|
||||||
|
# define FMT_GEN5(f) FMT_GEN4(f), f(5)
|
||||||
|
# define FMT_GEN6(f) FMT_GEN5(f), f(6)
|
||||||
|
# define FMT_GEN7(f) FMT_GEN6(f), f(7)
|
||||||
|
# define FMT_GEN8(f) FMT_GEN7(f), f(8)
|
||||||
|
# define FMT_GEN9(f) FMT_GEN8(f), f(9)
|
||||||
|
|
||||||
#define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
|
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
|
||||||
#define FMT_MAKE_ARG(n) const T##n &v##n
|
# define FMT_MAKE_ARG(n) const T##n &v##n
|
||||||
#define FMT_MAKE_REF(n) MakeArg(v##n)
|
# define FMT_MAKE_REF(n) fmt::Writer::MakeArg(v##n)
|
||||||
|
|
||||||
#define FMT_TEMPLATE(func_name, n) \
|
# define FMT_TEMPLATE(func, arg_type, n) \
|
||||||
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
||||||
inline void func_name(BasicStringRef<Char> format, FMT_GEN(n, FMT_MAKE_ARG)) { \
|
inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
|
||||||
const fmt::internal::ArgInfo args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
const fmt::internal::ArgInfo args[] = {FMT_GEN(n, FMT_MAKE_REF)}; \
|
||||||
func_name(format, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
func(arg1, fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines a variadic function returning void.
|
// Emulates a variadic function returning void on a pre-C++11 compiler.
|
||||||
#define FMT_VARIADIC_VOID(func_name) \
|
# define FMT_VARIADIC_VOID(func, arg_type) \
|
||||||
FMT_TEMPLATE(format, 1) FMT_TEMPLATE(format, 2) FMT_TEMPLATE(format, 3) \
|
FMT_TEMPLATE(func, arg_type, 1) FMT_TEMPLATE(func, arg_type, 2) \
|
||||||
FMT_TEMPLATE(format, 4) FMT_TEMPLATE(format, 5) FMT_TEMPLATE(format, 6) \
|
FMT_TEMPLATE(func, arg_type, 3) FMT_TEMPLATE(func, arg_type, 4) \
|
||||||
FMT_TEMPLATE(format, 7) FMT_TEMPLATE(format, 8) FMT_TEMPLATE(format, 9)
|
FMT_TEMPLATE(func, arg_type, 5) FMT_TEMPLATE(func, arg_type, 6) \
|
||||||
|
FMT_TEMPLATE(func, arg_type, 7) FMT_TEMPLATE(func, arg_type, 8) \
|
||||||
|
FMT_TEMPLATE(func, arg_type, 9)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -1204,13 +1225,39 @@ class BasicWriter {
|
|||||||
return std::basic_string<Char>(&buffer_[0], buffer_.size());
|
return std::basic_string<Char>(&buffer_[0], buffer_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Formats a string sending the output to the writer. This function
|
||||||
|
takes variable number of arguments.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
Writer out;
|
||||||
|
out.format("Current point:\n");
|
||||||
|
out.format("({:+f}, {:+f})", -3.14, 3.14);
|
||||||
|
|
||||||
|
This will write the following output to the ``out`` object:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
Current point:
|
||||||
|
(-3.140000, +3.140000)
|
||||||
|
|
||||||
|
The output can be accessed using :meth:`data`, :meth:`c_str` or :meth:`str`
|
||||||
|
methods.
|
||||||
|
|
||||||
|
See also `Format String Syntax`_.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
inline void format(BasicStringRef<Char> format, const ArgList &args) {
|
inline void format(BasicStringRef<Char> format, const ArgList &args) {
|
||||||
FormatParser().Format(*this, format, args);
|
FormatParser().Format(*this, format, args);
|
||||||
}
|
}
|
||||||
|
FMT_VARIADIC_VOID(format, fmt::BasicStringRef<Char>)
|
||||||
|
|
||||||
inline void printf(BasicStringRef<Char> format, const ArgList &args) {
|
inline void printf(BasicStringRef<Char> format, const ArgList &args) {
|
||||||
PrintfParser().Format(*this, format, args);
|
PrintfParser().Format(*this, format, args);
|
||||||
}
|
}
|
||||||
|
FMT_VARIADIC_VOID(printf, fmt::BasicStringRef<Char>)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -1240,47 +1287,9 @@ class BasicWriter {
|
|||||||
BasicFormatter<Char> Format(StringRef format);
|
BasicFormatter<Char> Format(StringRef format);
|
||||||
|
|
||||||
#if FMT_USE_VARIADIC_TEMPLATES
|
#if FMT_USE_VARIADIC_TEMPLATES
|
||||||
/**
|
// This function is deprecated, use Writer::format instead.
|
||||||
\rst
|
|
||||||
Formats a string sending the output to the writer.
|
|
||||||
|
|
||||||
This version of the Format method uses C++11 features such as
|
|
||||||
variadic templates and rvalue references. For C++98 version, see
|
|
||||||
the overload taking a single ``StringRef`` argument above.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
Writer out;
|
|
||||||
out.Format("Current point:\n");
|
|
||||||
out.Format("({:+f}, {:+f})", -3.14, 3.14);
|
|
||||||
|
|
||||||
This will write the following output to the ``out`` object:
|
|
||||||
|
|
||||||
.. code-block:: none
|
|
||||||
|
|
||||||
Current point:
|
|
||||||
(-3.140000, +3.140000)
|
|
||||||
|
|
||||||
The output can be accessed using :meth:`data`, :meth:`c_str` or :meth:`str`
|
|
||||||
methods.
|
|
||||||
|
|
||||||
See also `Format String Syntax`_.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void Format(BasicStringRef<Char> format, const Args & ... args) {
|
FMT_DEPRECATED(void Format(BasicStringRef<Char> format, const Args & ... args));
|
||||||
BasicArg<> arg_array[] = {args...};
|
|
||||||
this->format(format, ArgList(arg_array, sizeof...(Args)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void printf(BasicStringRef<Char> format, const Args & ... args) {
|
|
||||||
BasicArg<> arg_array[internal::NonZero<sizeof...(Args)>::VALUE] = {args...};
|
|
||||||
this->printf(format, ArgList(arg_array, sizeof...(Args)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
FMT_VARIADIC_VOID(format)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1955,6 +1964,13 @@ inline Formatter<ANSITerminalSink> PrintColored(Color c, StringRef format) {
|
|||||||
|
|
||||||
#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES
|
#if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
template<typename... Args>
|
||||||
|
void BasicWriter<Char>::Format(
|
||||||
|
BasicStringRef<Char> format, const Args & ... args) {
|
||||||
|
this->format(format, args...);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
Formats a string similarly to Python's `str.format
|
Formats a string similarly to Python's `str.format
|
||||||
@ -2165,7 +2181,7 @@ inline void FormatDec(char *&buffer, T value) {
|
|||||||
|
|
||||||
#define FMT_ADD_ARG_NAME(type, index) type arg##index
|
#define FMT_ADD_ARG_NAME(type, index) type arg##index
|
||||||
#define FMT_GET_ARG_NAME(type, index) arg##index
|
#define FMT_GET_ARG_NAME(type, index) arg##index
|
||||||
#define FMT_MAKE_ARG(arg, index) fmt::Writer::MakeArg(arg)
|
#define FMT_MAKE_ARG2(arg, index) fmt::Writer::MakeArg(arg)
|
||||||
|
|
||||||
#define FMT_VARIADIC(return_type, func_name, ...) \
|
#define FMT_VARIADIC(return_type, func_name, ...) \
|
||||||
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \
|
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \
|
||||||
@ -2175,14 +2191,14 @@ inline void FormatDec(char *&buffer, T value) {
|
|||||||
template <typename T1> \
|
template <typename T1> \
|
||||||
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
const T1 &v1) { \
|
const T1 &v1) { \
|
||||||
const fmt::internal::ArgInfo args[] = {FMT_FOR_EACH(FMT_MAKE_ARG, v1)}; \
|
const fmt::internal::ArgInfo args[] = {FMT_FOR_EACH(FMT_MAKE_ARG2, v1)}; \
|
||||||
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
||||||
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
||||||
} \
|
} \
|
||||||
template <typename T1, typename T2> \
|
template <typename T1, typename T2> \
|
||||||
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
const T1 &v1, const T2 &v2) { \
|
const T1 &v1, const T2 &v2) { \
|
||||||
const fmt::internal::ArgInfo args[] = {FMT_FOR_EACH(FMT_MAKE_ARG, v1, v2)}; \
|
const fmt::internal::ArgInfo args[] = {FMT_FOR_EACH(FMT_MAKE_ARG2, v1, v2)}; \
|
||||||
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
||||||
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
||||||
} \
|
} \
|
||||||
@ -2190,7 +2206,7 @@ inline void FormatDec(char *&buffer, T value) {
|
|||||||
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
const T1 &v1, const T2 &v2, const T3 &v3) { \
|
const T1 &v1, const T2 &v2, const T3 &v3) { \
|
||||||
const fmt::internal::ArgInfo args[] = { \
|
const fmt::internal::ArgInfo args[] = { \
|
||||||
FMT_FOR_EACH(FMT_MAKE_ARG, v1, v2, v3) \
|
FMT_FOR_EACH(FMT_MAKE_ARG2, v1, v2, v3) \
|
||||||
}; \
|
}; \
|
||||||
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
||||||
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
||||||
@ -2199,7 +2215,7 @@ inline void FormatDec(char *&buffer, T value) {
|
|||||||
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) { \
|
const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) { \
|
||||||
const fmt::internal::ArgInfo args[] = { \
|
const fmt::internal::ArgInfo args[] = { \
|
||||||
FMT_FOR_EACH(FMT_MAKE_ARG, v1, v2, v3, v4) \
|
FMT_FOR_EACH(FMT_MAKE_ARG2, v1, v2, v3, v4) \
|
||||||
}; \
|
}; \
|
||||||
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
||||||
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
||||||
@ -2208,7 +2224,7 @@ inline void FormatDec(char *&buffer, T value) {
|
|||||||
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
inline return_type func_name(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||||
const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) { \
|
const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) { \
|
||||||
const fmt::internal::ArgInfo args[] = { \
|
const fmt::internal::ArgInfo args[] = { \
|
||||||
FMT_FOR_EACH(FMT_MAKE_ARG, v1, v2, v3, v4, v5) \
|
FMT_FOR_EACH(FMT_MAKE_ARG2, v1, v2, v3, v4, v5) \
|
||||||
}; \
|
}; \
|
||||||
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
return func_name(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
|
||||||
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
fmt::ArgList(args, sizeof(args) / sizeof(*args))); \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user