Migrate docs and cleanup

This commit is contained in:
Victor Zverovich 2024-06-02 13:17:04 -07:00
parent 97117cbb51
commit ab29ef37d9
10 changed files with 125 additions and 149 deletions

View File

@ -434,7 +434,7 @@ variable `FMT_ENFORCE_COMPILE_STRING`. When set, functions accepting
<a id="ranges-api"></a> <a id="ranges-api"></a>
## Range and Tuple Formatting ## Range and Tuple Formatting
The library also supports convenient formatting of ranges and tuples: `fmt/ranges.h` provides formatting support for ranges and tuples:
#include <fmt/ranges.h> #include <fmt/ranges.h>
@ -453,14 +453,17 @@ Using `fmt::join`, you can separate tuple elements with a custom separator:
::: join(It, Sentinel, string_view) ::: join(It, Sentinel, string_view)
::: join(std::initializer_list<T>, string_view)
<a id="chrono-api"></a> <a id="chrono-api"></a>
## Date and Time Formatting ## Date and Time Formatting
`fmt/chrono.h` provides formatters for `fmt/chrono.h` provides formatters for
- [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration) - [`std::chrono::duration`](https://en.cppreference.com/w/cpp/chrono/duration)
- [std::chrono::time_point](https://en.cppreference.com/w/cpp/chrono/time_point) - [`std::chrono::time_point`](
- [std::tm](https://en.cppreference.com/w/cpp/chrono/c/tm) https://en.cppreference.com/w/cpp/chrono/time_point)
- [`std::tm`](https://en.cppreference.com/w/cpp/chrono/c/tm)
The format syntax is described in [Chrono Format Specifications](syntax.md# The format syntax is described in [Chrono Format Specifications](syntax.md#
chrono-format-specifications). chrono-format-specifications).

View File

@ -1,7 +1,8 @@
# Format String Syntax # Format String Syntax
[Formatting functions](api.md) such as `fmt::format` and [`fmt::print`]( [Formatting functions](api.md) such as [`fmt::format`](api.md#format) and
api.md#print) use the same format string syntax described in this section. [`fmt::print`]( api.md#print) use the same format string syntax described
in this section.
Format strings contain "replacement fields" surrounded by curly braces `{}`. Format strings contain "replacement fields" surrounded by curly braces `{}`.
Anything that is not contained in braces is considered literal text, which is Anything that is not contained in braces is considered literal text, which is

View File

@ -96,10 +96,8 @@ FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec)
return static_cast<To>(from); return static_cast<To>(from);
} }
/** /// Converts From to To, without loss. If the dynamic value of from
* converts From to To, without loss. If the dynamic value of from /// can't be converted to To without loss, ec is set.
* can't be converted to To without loss, ec is set.
*/
template <typename To, typename From, template <typename To, typename From,
FMT_ENABLE_IF(!std::is_same<From, To>::value && FMT_ENABLE_IF(!std::is_same<From, To>::value &&
std::numeric_limits<From>::is_signed != std::numeric_limits<From>::is_signed !=
@ -187,9 +185,7 @@ FMT_CONSTEXPR auto safe_float_conversion(const From from, int& ec) -> To {
return from; return from;
} }
/** /// Safe duration cast between integral durations
* safe duration cast between integral durations
*/
template <typename To, typename FromRep, typename FromPeriod, template <typename To, typename FromRep, typename FromPeriod,
FMT_ENABLE_IF(std::is_integral<FromRep>::value), FMT_ENABLE_IF(std::is_integral<FromRep>::value),
FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)> FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)>
@ -239,9 +235,7 @@ auto safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
return ec ? To() : To(tocount); return ec ? To() : To(tocount);
} }
/** /// Safe duration_cast between floating point durations
* safe duration_cast between floating point durations
*/
template <typename To, typename FromRep, typename FromPeriod, template <typename To, typename FromRep, typename FromPeriod,
FMT_ENABLE_IF(std::is_floating_point<FromRep>::value), FMT_ENABLE_IF(std::is_floating_point<FromRep>::value),
FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)> FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)>
@ -518,9 +512,9 @@ auto to_time_t(
FMT_BEGIN_EXPORT FMT_BEGIN_EXPORT
/** /**
Converts given time since epoch as ``std::time_t`` value into calendar time, * Converts given time since epoch as `std::time_t` value into calendar time,
expressed in local time. Unlike ``std::localtime``, this function is * expressed in local time. Unlike `std::localtime`, this function is
thread-safe on most platforms. * thread-safe on most platforms.
*/ */
inline auto localtime(std::time_t time) -> std::tm { inline auto localtime(std::time_t time) -> std::tm {
struct dispatcher { struct dispatcher {
@ -567,9 +561,9 @@ inline auto localtime(std::chrono::local_time<Duration> time) -> std::tm {
#endif #endif
/** /**
Converts given time since epoch as ``std::time_t`` value into calendar time, * Converts given time since epoch as `std::time_t` value into calendar time,
expressed in Coordinated Universal Time (UTC). Unlike ``std::gmtime``, this * expressed in Coordinated Universal Time (UTC). Unlike `std::gmtime`, this
function is thread-safe on most platforms. * function is thread-safe on most platforms.
*/ */
inline auto gmtime(std::time_t time) -> std::tm { inline auto gmtime(std::time_t time) -> std::tm {
struct dispatcher { struct dispatcher {

View File

@ -227,7 +227,7 @@ struct color_type {
}; };
} // namespace detail } // namespace detail
/** A text style consisting of foreground and background colors and emphasis. */ /// A text style consisting of foreground and background colors and emphasis.
class text_style { class text_style {
public: public:
FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept
@ -310,13 +310,13 @@ class text_style {
emphasis ems; emphasis ems;
}; };
/** Creates a text style from the foreground (text) color. */ /// Creates a text style from the foreground (text) color.
FMT_CONSTEXPR inline auto fg(detail::color_type foreground) noexcept FMT_CONSTEXPR inline auto fg(detail::color_type foreground) noexcept
-> text_style { -> text_style {
return text_style(true, foreground); return text_style(true, foreground);
} }
/** Creates a text style from the background color. */ /// Creates a text style from the background color.
FMT_CONSTEXPR inline auto bg(detail::color_type background) noexcept FMT_CONSTEXPR inline auto bg(detail::color_type background) noexcept
-> text_style { -> text_style {
return text_style(false, background); return text_style(false, background);
@ -474,15 +474,13 @@ inline void vprint(FILE* f, const text_style& ts, string_view fmt,
} }
/** /**
\rst * Formats a string and prints it to the specified file stream using ANSI
Formats a string and prints it to the specified file stream using ANSI * escape sequences to specify text formatting.
escape sequences to specify text formatting. *
* **Example**:
**Example**: *
* fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
fmt::print(fmt::emphasis::bold | fg(fmt::color::red), * "Elapsed time: {0:.2f} seconds", 1.23);
"Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/ */
template <typename... T> template <typename... T>
void print(FILE* f, const text_style& ts, format_string<T...> fmt, void print(FILE* f, const text_style& ts, format_string<T...> fmt,
@ -491,15 +489,13 @@ void print(FILE* f, const text_style& ts, format_string<T...> fmt,
} }
/** /**
\rst * Formats a string and prints it to stdout using ANSI escape sequences to
Formats a string and prints it to stdout using ANSI escape sequences to * specify text formatting.
specify text formatting. *
* **Example**:
**Example**: *
* fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
fmt::print(fmt::emphasis::bold | fg(fmt::color::red), * "Elapsed time: {0:.2f} seconds", 1.23);
"Elapsed time: {0:.2f} seconds", 1.23);
\endrst
*/ */
template <typename... T> template <typename... T>
void print(const text_style& ts, format_string<T...> fmt, T&&... args) { void print(const text_style& ts, format_string<T...> fmt, T&&... args) {
@ -514,26 +510,24 @@ inline auto vformat(const text_style& ts, string_view fmt, format_args args)
} }
/** /**
\rst * Formats arguments and returns the result as a string using ANSI escape
Formats arguments and returns the result as a string using ANSI * sequences to specify text formatting.
escape sequences to specify text formatting. *
* **Example**:
**Example**: *
* ```
#include <fmt/color.h> * #include <fmt/color.h>
std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), * std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
"The answer is {}", 42); * "The answer is {}", 42);
\endrst * ```
*/ */
template <typename... T> template <typename... T>
inline auto format(const text_style& ts, format_string<T...> fmt, T&&... args) inline auto format(const text_style& ts, format_string<T...> fmt, T&&... args)
-> std::string { -> std::string {
return fmt::vformat(ts, fmt, fmt::make_format_args(args...)); return fmt::vformat(ts, fmt, fmt::make_format_args(args...));
} }
/** /// Formats a string with the given text_style and writes the output to `out`.
Formats a string with the given text_style and writes the output to ``out``.
*/
template <typename OutputIt, template <typename OutputIt,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
auto vformat_to(OutputIt out, const text_style& ts, string_view fmt, auto vformat_to(OutputIt out, const text_style& ts, string_view fmt,
@ -544,17 +538,15 @@ auto vformat_to(OutputIt out, const text_style& ts, string_view fmt,
} }
/** /**
\rst * Formats arguments with the given text style, writes the result to the output
Formats arguments with the given text_style, writes the result to the output * iterator `out` and returns the iterator past the end of the output range.
iterator ``out`` and returns the iterator past the end of the output range. *
* **Example**:
**Example**: *
* std::vector<char> out;
std::vector<char> out; * fmt::format_to(std::back_inserter(out),
fmt::format_to(std::back_inserter(out), * fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
fmt::emphasis::bold | fg(fmt::color::red), "{}", 42); */
\endrst
*/
template <typename OutputIt, typename... T, template <typename OutputIt, typename... T,
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
inline auto format_to(OutputIt out, const text_style& ts, inline auto format_to(OutputIt out, const text_style& ts,
@ -599,16 +591,14 @@ struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
}; };
/** /**
\rst * Returns an argument that will be formatted using ANSI escape sequences,
Returns an argument that will be formatted using ANSI escape sequences, * to be used in a formatting function.
to be used in a formatting function. *
* **Example**:
**Example**: *
* fmt::print("Elapsed time: {0:.2f} seconds",
fmt::print("Elapsed time: {0:.2f} seconds", * fmt::styled(1.23, fmt::fg(fmt::color::green) |
fmt::styled(1.23, fmt::fg(fmt::color::green) | * fmt::bg(fmt::color::blue)));
fmt::bg(fmt::color::blue)));
\endrst
*/ */
template <typename T> template <typename T>
FMT_CONSTEXPR auto styled(const T& value, text_style ts) FMT_CONSTEXPR auto styled(const T& value, text_style ts)

View File

@ -238,13 +238,12 @@ constexpr size_t parse_text(basic_string_view<Char> str, size_t pos) {
} }
template <typename Args, size_t POS, int ID, typename S> template <typename Args, size_t POS, int ID, typename S>
constexpr auto compile_format_string(S format_str); constexpr auto compile_format_string(S fmt);
template <typename Args, size_t POS, int ID, typename T, typename S> template <typename Args, size_t POS, int ID, typename T, typename S>
constexpr auto parse_tail(T head, S format_str) { constexpr auto parse_tail(T head, S fmt) {
if constexpr (POS != if constexpr (POS != basic_string_view<typename S::char_type>(fmt).size()) {
basic_string_view<typename S::char_type>(format_str).size()) { constexpr auto tail = compile_format_string<Args, POS, ID>(fmt);
constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
if constexpr (std::is_same<remove_cvref_t<decltype(tail)>, if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
unknown_format>()) unknown_format>())
return tail; return tail;
@ -315,14 +314,13 @@ struct field_type<T, enable_if_t<detail::is_named_arg<T>::value>> {
template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID, template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID,
typename S> typename S>
constexpr auto parse_replacement_field_then_tail(S format_str) { constexpr auto parse_replacement_field_then_tail(S fmt) {
using char_type = typename S::char_type; using char_type = typename S::char_type;
constexpr auto str = basic_string_view<char_type>(format_str); constexpr auto str = basic_string_view<char_type>(fmt);
constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type(); constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type();
if constexpr (c == '}') { if constexpr (c == '}') {
return parse_tail<Args, END_POS + 1, NEXT_ID>( return parse_tail<Args, END_POS + 1, NEXT_ID>(
field<char_type, typename field_type<T>::type, ARG_INDEX>(), field<char_type, typename field_type<T>::type, ARG_INDEX>(), fmt);
format_str);
} else if constexpr (c != ':') { } else if constexpr (c != ':') {
FMT_THROW(format_error("expected ':'")); FMT_THROW(format_error("expected ':'"));
} else { } else {
@ -335,7 +333,7 @@ constexpr auto parse_replacement_field_then_tail(S format_str) {
return parse_tail<Args, result.end + 1, result.next_arg_id>( return parse_tail<Args, result.end + 1, result.next_arg_id>(
spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{ spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
result.fmt}, result.fmt},
format_str); fmt);
} }
} }
} }
@ -343,22 +341,21 @@ constexpr auto parse_replacement_field_then_tail(S format_str) {
// Compiles a non-empty format string and returns the compiled representation // Compiles a non-empty format string and returns the compiled representation
// or unknown_format() on unrecognized input. // or unknown_format() on unrecognized input.
template <typename Args, size_t POS, int ID, typename S> template <typename Args, size_t POS, int ID, typename S>
constexpr auto compile_format_string(S format_str) { constexpr auto compile_format_string(S fmt) {
using char_type = typename S::char_type; using char_type = typename S::char_type;
constexpr auto str = basic_string_view<char_type>(format_str); constexpr auto str = basic_string_view<char_type>(fmt);
if constexpr (str[POS] == '{') { if constexpr (str[POS] == '{') {
if constexpr (POS + 1 == str.size()) if constexpr (POS + 1 == str.size())
FMT_THROW(format_error("unmatched '{' in format string")); FMT_THROW(format_error("unmatched '{' in format string"));
if constexpr (str[POS + 1] == '{') { if constexpr (str[POS + 1] == '{') {
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str); return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), fmt);
} else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') { } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') {
static_assert(ID != manual_indexing_id, static_assert(ID != manual_indexing_id,
"cannot switch from manual to automatic argument indexing"); "cannot switch from manual to automatic argument indexing");
constexpr auto next_id = constexpr auto next_id =
ID != manual_indexing_id ? ID + 1 : manual_indexing_id; ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
return parse_replacement_field_then_tail<get_type<ID, Args>, Args, return parse_replacement_field_then_tail<get_type<ID, Args>, Args,
POS + 1, ID, next_id>( POS + 1, ID, next_id>(fmt);
format_str);
} else { } else {
constexpr auto arg_id_result = constexpr auto arg_id_result =
parse_arg_id<ID>(str.data() + POS + 1, str.data() + str.size()); parse_arg_id<ID>(str.data() + POS + 1, str.data() + str.size());
@ -374,7 +371,7 @@ constexpr auto compile_format_string(S format_str) {
return parse_replacement_field_then_tail<get_type<arg_index, Args>, return parse_replacement_field_then_tail<get_type<arg_index, Args>,
Args, arg_id_end_pos, Args, arg_id_end_pos,
arg_index, manual_indexing_id>( arg_index, manual_indexing_id>(
format_str); fmt);
} else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) { } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) {
constexpr auto arg_index = constexpr auto arg_index =
get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{}); get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{});
@ -383,11 +380,11 @@ constexpr auto compile_format_string(S format_str) {
ID != manual_indexing_id ? ID + 1 : manual_indexing_id; ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
return parse_replacement_field_then_tail< return parse_replacement_field_then_tail<
decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos, decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos,
arg_index, next_id>(format_str); arg_index, next_id>(fmt);
} else if constexpr (c == '}') { } else if constexpr (c == '}') {
return parse_tail<Args, arg_id_end_pos + 1, ID>( return parse_tail<Args, arg_id_end_pos + 1, ID>(
runtime_named_field<char_type>{arg_id_result.arg_id.val.name}, runtime_named_field<char_type>{arg_id_result.arg_id.val.name},
format_str); fmt);
} else if constexpr (c == ':') { } else if constexpr (c == ':') {
return unknown_format(); // no type info for specs parsing return unknown_format(); // no type info for specs parsing
} }
@ -396,29 +393,26 @@ constexpr auto compile_format_string(S format_str) {
} else if constexpr (str[POS] == '}') { } else if constexpr (str[POS] == '}') {
if constexpr (POS + 1 == str.size()) if constexpr (POS + 1 == str.size())
FMT_THROW(format_error("unmatched '}' in format string")); FMT_THROW(format_error("unmatched '}' in format string"));
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str); return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), fmt);
} else { } else {
constexpr auto end = parse_text(str, POS + 1); constexpr auto end = parse_text(str, POS + 1);
if constexpr (end - POS > 1) { if constexpr (end - POS > 1) {
return parse_tail<Args, end, ID>(make_text(str, POS, end - POS), return parse_tail<Args, end, ID>(make_text(str, POS, end - POS), fmt);
format_str);
} else { } else {
return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]}, return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]}, fmt);
format_str);
} }
} }
} }
template <typename... Args, typename S, template <typename... Args, typename S,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
constexpr auto compile(S format_str) { constexpr auto compile(S fmt) {
constexpr auto str = basic_string_view<typename S::char_type>(format_str); constexpr auto str = basic_string_view<typename S::char_type>(fmt);
if constexpr (str.size() == 0) { if constexpr (str.size() == 0) {
return detail::make_text(str, 0, 0); return detail::make_text(str, 0, 0);
} else { } else {
constexpr auto result = constexpr auto result =
detail::compile_format_string<detail::type_list<Args...>, 0, 0>( detail::compile_format_string<detail::type_list<Args...>, 0, 0>(fmt);
format_str);
return result; return result;
} }
} }
@ -490,35 +484,33 @@ FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {
template <typename OutputIt, typename S, typename... Args, template <typename OutputIt, typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
auto format_to_n(OutputIt out, size_t n, const S& format_str, Args&&... args) auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args)
-> format_to_n_result<OutputIt> { -> format_to_n_result<OutputIt> {
using traits = detail::fixed_buffer_traits; using traits = detail::fixed_buffer_traits;
auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n); auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
fmt::format_to(std::back_inserter(buf), format_str, fmt::format_to(std::back_inserter(buf), fmt, std::forward<Args>(args)...);
std::forward<Args>(args)...);
return {buf.out(), buf.count()}; return {buf.out(), buf.count()};
} }
template <typename S, typename... Args, template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
FMT_CONSTEXPR20 auto formatted_size(const S& format_str, const Args&... args) FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args)
-> size_t { -> size_t {
return fmt::format_to(detail::counting_iterator(), format_str, args...) return fmt::format_to(detail::counting_iterator(), fmt, args...).count();
.count();
} }
template <typename S, typename... Args, template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
void print(std::FILE* f, const S& format_str, const Args&... args) { void print(std::FILE* f, const S& fmt, const Args&... args) {
memory_buffer buffer; memory_buffer buffer;
fmt::format_to(std::back_inserter(buffer), format_str, args...); fmt::format_to(std::back_inserter(buffer), fmt, args...);
detail::print(f, {buffer.data(), buffer.size()}); detail::print(f, {buffer.data(), buffer.size()});
} }
template <typename S, typename... Args, template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
void print(const S& format_str, const Args&... args) { void print(const S& fmt, const Args&... args) {
print(stdout, format_str, args...); print(stdout, fmt, args...);
} }
#if FMT_USE_NONTYPE_TEMPLATE_ARGS #if FMT_USE_NONTYPE_TEMPLATE_ARGS

View File

@ -4343,7 +4343,7 @@ FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
* *
* #include <fmt/format.h> * #include <fmt/format.h>
* std::string message = fmt::format("The answer is {}.", 42); * std::string message = fmt::format("The answer is {}.", 42);
*/ */
template <typename... T> template <typename... T>
FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args) FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)
-> std::string { -> std::string {

View File

@ -405,7 +405,8 @@ class file_buffer final : public buffer<char> {
// occur in Xcode versions 7.2.1 and 8.2.1. // occur in Xcode versions 7.2.1 and 8.2.1.
constexpr detail::buffer_size buffer_size{}; constexpr detail::buffer_size buffer_size{};
/** A fast output stream which is not thread-safe. */ /// A fast output stream for writing from a single thread. Writing from
/// multiple threads without external synchronization may result in a data race.
class FMT_API ostream { class FMT_API ostream {
private: private:
FMT_MSC_WARNING(suppress : 4251) FMT_MSC_WARNING(suppress : 4251)
@ -426,10 +427,8 @@ class FMT_API ostream {
void close() { buffer_.close(); } void close() { buffer_.close(); }
/** /// Formats `args` according to specifications in `fmt` and writes the
Formats ``args`` according to specifications in ``fmt`` and writes the /// output to the file.
output to the file.
*/
template <typename... T> void print(format_string<T...> fmt, T&&... args) { template <typename... T> void print(format_string<T...> fmt, T&&... args) {
vformat_to(appender(buffer_), fmt, fmt::make_format_args(args...)); vformat_to(appender(buffer_), fmt, fmt::make_format_args(args...));
} }

View File

@ -670,7 +670,7 @@ auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
* *
* **Example**: * **Example**:
* *
* std::vector<int> v = {1, 2, 3}; * auto v = std::vector<int>{1, 2, 3};
* fmt::print("{}", fmt::join(v, ", ")); * fmt::print("{}", fmt::join(v, ", "));
* // Output: 1, 2, 3 * // Output: 1, 2, 3
* *
@ -802,15 +802,13 @@ struct formatter<
FMT_BEGIN_EXPORT FMT_BEGIN_EXPORT
/** /**
\rst * Returns an object that formats `std::tuple` with elements separated by `sep`.
Returns an object that formats `tuple` with elements separated by `sep`. *
* **Example**:
**Example**: *
* auto t = std::tuple<int, char>{1, 'a'};
std::tuple<int, char> t = {1, 'a'}; * fmt::print("{}", fmt::join(t, ", "));
fmt::print("{}", fmt::join(t, ", ")); * // Output: 1, a
// Output: "1, a"
\endrst
*/ */
template <typename... T> template <typename... T>
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep) FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
@ -819,15 +817,13 @@ FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
} }
/** /**
\rst * Returns an object that formats `std::initializer_list` with elements
Returns an object that formats `initializer_list` with elements separated by * separated by `sep`.
`sep`. *
* **Example**:
**Example**: *
* fmt::print("{}", fmt::join({1, 2, 3}, ", "));
fmt::print("{}", fmt::join({1, 2, 3}, ", ")); * // Output: "1, 2, 3"
// Output: "1, 2, 3"
\endrst
*/ */
template <typename T> template <typename T>
auto join(std::initializer_list<T> list, string_view sep) auto join(std::initializer_list<T> list, string_view sep)

View File

@ -10,10 +10,11 @@ from subprocess import CalledProcessError, PIPE, Popen, STDOUT
class Definition: class Definition:
'''A definition extracted by Doxygen.''' '''A definition extracted by Doxygen.'''
def __init__(self, name: str, kind: Optional[str] = None, def __init__(self, name: str, kind: Optional[str] = None,
node: Optional[et.Element] = None): node: Optional[et.Element] = None,
is_member: bool = False):
self.name = name self.name = name
self.kind = kind if kind is not None else node.get('kind') self.kind = kind if kind is not None else node.get('kind')
self.id = node.get('id') if node is not None else None self.id = name if not is_member else None
self.params = None self.params = None
self.members = None self.members = None
@ -225,7 +226,7 @@ class CxxHandler(BaseHandler):
if len(desc) == 0: if len(desc) == 0:
continue continue
kind = m.get('kind') kind = m.get('kind')
member = Definition(name if name else '', kind) member = Definition(name if name else '', kind=kind, is_member=True)
type = m.find('type').text type = m.find('type').text
member.type = type if type else '' member.type = type if type else ''
if kind == 'function': if kind == 'function':
@ -274,9 +275,9 @@ class CxxHandler(BaseHandler):
elif d.kind == 'define': elif d.kind == 'define':
params = [] params = []
for p in node.findall('param'): for p in node.findall('param'):
d = Definition(p.find('defname').text, 'param') param = Definition(p.find('defname').text, kind='param')
d.type = None param.type = None
params.append(d) params.append(param)
d.type = convert_type(node.find('type')) d.type = convert_type(node.find('type'))
d.template_params = convert_template_params(node) d.template_params = convert_template_params(node)
d.params = params d.params = params