fmt的API介紹
本文翻譯:https://fmt.dev/latest/api.html
水平有限,僅供參考,歡迎指正。 有興趣的,看看原文。
--------------------------------------------------------------------------
A、介紹
fmt庫由一下模組組成:
fmt/core.h: 提供引數處理的一系列介面 和 一個輕量級的格式化函式集合。
fmt/format.h: 提供了用於編譯時的格式化字串檢查、寬字元、迭代輸出 和支援使用者子自定義的介面。
fmt/ranges.h: 提供了針對元組和容器ranges的額外的格式化支援
fmt/chrono.h: 提供了時間和日期的格式化處理的介面
fmt/compile.h: 格式化字串編譯
fmt/ostream.h: 標準輸出流的支援
fmt/printf.h: printf格式化
fmt庫提供的函式和型別都在fmt的名稱空間下和加上了字首 FMT_
注意: fmt格式化都是在大括號 {}內。
B、core api
0、包含標頭檔案:
#include <fmt/core.h>
1、fmt::foroomat返回一個字串。
std::string message = fmt::format("The answer is {} ", 42);
2、fmt::print標準輸出, 與 std::cout的輸出相仿
#include <fmt/core.h>
fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
3、fmt::print支援寫入檔案,寫入的字串是用的UNICODE編碼。函式原型如下:
template <typename S, typename... Args, typename Char = char_t<S>> void fmt::print(std::FILE *f, const S &format_str, Args&&... args)
函式的第一個引數是檔案指標:
fmt::print(stderr, "Don't {}!", "panic");
4、命名引數:通過指定引數名稱的方式來呼叫引數。方便呼叫引數時按呼叫者的需要來排列順序,而不必死守函式宣告時的順序,同時結合預設引數值的特性,可以選擇使用預設引數還是不使用預設引數。 函式原型如下:
template <typename Char, typename T>
detail::named_arg<Char, T> fmt::arg(const Char *name, const T &arg)
該函式將返回一個用於函式引數的格式化字串。使用方法:
fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
注意: 命名引數不能在編譯的時候檢查格式化字串的錯誤
5、引數列表 Argument Lists
5.1)、函式原型:
template <typename Context = format_context, typename... Args>
format_arg_store<Context, Args...> fmt::make_format_args(const Args&... args)
構造一個format_arg_store物件,該物件包含對引數的引用,並且可以隱式轉換為format_args。可以省略上下文,在這種情況下,它預設為上下文。
有關生命週期的考慮,請參見arg()。
5.2)、class fmt::format_arg_store類
template <typename Context, typename... Args>
class fmt::format_arg_store
引用引數的陣列。可以將其隱式轉換為basic_format_args,以傳遞給型別擦除的格式函式,例如vformat()。
fmt::format_arg_store 的公有函式:
5.2.1)、push_back函式原型
template <typename T>
void push_back(const T &arg)
該函式將引數arg自動新增到自動儲存的記憶體中,以便傳遞給需要格式化引數的函式。
請注意,如有必要,將自定義型別和字串型別(但不包括字串view)複製到儲存中,以動態分配記憶體, 例如:
fmt::dynamic_format_arg_store<fmt::format_context> store;
store.push_back(42);
store.push_back("abc");
store.push_back(1.5f);
std::string result = fmt::vformat("{} and {} and {}", store);
5.2.2)、 push_back函式原型:
template <typename T>
void push_back(std::reference_wrapper<T> arg)
該函式將引數arg自動新增到自動儲存的記憶體中,以便傳遞給需要格式化引數的函式。通過std :: ref()/ std :: cref()的引用,支援包裝在std :: reference_wrapper中的命名引數。例如:
fmt::dynamic_format_arg_store<fmt::format_context> store;
char str[] = "1234567890";
store.push_back(std::cref(str));
int a1_val{42};
auto a1 = fmt::arg("a1_", a1_val);
store.push_back(std::cref(a1));
// Changing str affects the output but only for string and custom types.
str[0] = 'X';
std::string result = fmt::vformat("{} and {a1_}");
assert(result == "X234567890 and 42");
5.2.3)、push_back 函式原型:
template <typename T>
void push_back(const detail::named_arg<char_type, T> &arg)
將命名引數新增到動態儲存中,以便以後傳遞給格式化函式。std::reference_wrapper可以避免參數傳遞時的拷貝。
5.2.4)、clear原型:
void clear()
該函式將清除儲存中的所有引數。
5.2.5)、reserve函式原型:
void reserve(size_t new_cap, size_t new_cap_named)
保留儲存空間以至於能容納new_cap引數,也包括new_cap_named 的命名引數。
5.3)、class fmt::basic_format_args類
template <typename Context>
class fmt::basic_format_args
格式化引數集合的檢視。 為了避免生命週期的問題,它僅應在型別擦除的函式中用作引數型別,例如vformat函式:
void vlog(string_view format_str, format_args args); // OK
format_args args = make_format_args(42); // Error: dangling reference
其公有函式:
5.3.1)、basic_format_args過載:
template <typename... Args>
basic_format_args(const format_arg_store<Context, Args...> &store)
從format_arg_store 構造一個 basic_format_args 物件。
5.3.2)、basic_format_args過載:
basic_format_args(const dynamic_format_arg_store<Context> &store)
從 dynamic_format_arg_store 構造一個 basic_format_args 物件。
5.3.3)、basic_format_args過載:
basic_format_args(const format_arg *args, int count)
根據一組動態引數構造一個basic_format_args物件。
5.4)、format_arg 的get函式原型:
format_arg get(int id) const
返回具有指定ID的引數。
5.5)、結構體 fmt::format_args
fmt::format_args是【basic_format_args<context>】的別名,繼承 fmt::basic_format_args< format_context >
5.6)、類 fmt::basic_format_arg:
template <typename Context>
class fmt::basic_format_arg
6、相容性
類fmt::basic_string_view
template <typename Char>
class fmt::basic_string_view
c++17以前, std::basic_string_view 的實現,其提供了一個子集的API
fmt::basic_string_view 可以用來格式化字串,即使std::string_view可以有效避免當使用與客戶端程式碼不同的-std選項編譯庫時問題:
公有函式:
6.1)、basic_string_view過載
constexpr basic_string_view(const Char *s, size_t count)
根據C字串和大小,構造一個字串引用物件。
6.2)、basic_string_view過載
basic_string_view(const Char *s)
從C字串構造一個字串引用物件,該字串使用std :: char_traits <Char> :: length計算大小。
6.3)、basic_string_view過載
template <typename Traits, typename Alloc>
basic_string_view(const std::basic_string<Char, Traits, Alloc> &s)
從std :: basic_string物件構造一個字串引用。
6.4)、data原型:
constexpr const Char *data() const
返回指向字串資料的指標。
6.5)、size
constexpr size_t size() const
返回字串的大小
該類提供了對寬字元的支援
using fmt::string_view = typedef basic_string_view<char>
using fmt::wstring_view = typedef basic_string_view<wchar_t>
7、本地化
預設情況下,所有格式化與語言環境無關。使用'n'格式,從本地語言環境中插入適當的數字分隔符,例如:
#include <fmt/core.h>
#include <locale>
std::locale::global(std::locale("en_US.UTF-8"));
auto s = fmt::format("{:L}", 1000000); // s == "1,000,000"
C、format API
fmt/format.h定義了完整格式化的API,提供了編譯時格式字串檢查,寬字串,輸出迭代器和使用者定義的型別支援。
內建格式和字串型別以及格式定義專長中具有constexpr解析函式的使用者定義型別均支援編譯時檢查。
1、FMT_STRING(s)
從字串常量s構造一個編譯時格式字串。例如:
// A compile-time error because 'd' is an invalid specifier for strings.
std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
2、格式化使用者定義的型別
要建立使用者定義的型別格式表,請專門設定formatter <T>結構模板並實現解析和格式化方法:
#include <fmt/format.h>
struct point { double x, y; };
template <>
struct fmt::formatter<point> {
// Presentation format: 'f' - fixed, 'e' - exponential.
char presentation = 'f';
// Parses format specifications of the form ['f' | 'e'].
constexpr auto parse(format_parse_context& ctx) {
// auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) // c++11
// [ctx.begin(), ctx.end()) is a character range that contains a part of
// the format string starting from the format specifications to be parsed,
// e.g. in
//
// fmt::format("{:f} - point of interest", point{1, 2});
//
// the range will contain "f} - point of interest". The formatter should
// parse specifiers until '}' or the end of the range. In this example
// the formatter should parse the 'f' specifier and return an iterator
// pointing to '}'.
// Parse the presentation format and store it in the formatter:
auto it = ctx.begin(), end = ctx.end();
if (it != end && (*it == 'f' || *it == 'e')) presentation = *it++;
// Check if reached the end of the range:
if (it != end && *it != '}')
throw format_error("invalid format");
// Return an iterator past the end of the parsed range:
return it;
}
// Formats the point p using the parsed format specification (presentation)
// stored in this formatter.
template <typename FormatContext>
auto format(const point& p, FormatContext& ctx) {
// auto format(const point &p, FormatContext &ctx) -> decltype(ctx.out()) // c++11
// ctx.out() is an output iterator to write to.
return format_to(
ctx.out(),
presentation == 'f' ? "({:.1f}, {:.1f})" : "({:.1e}, {:.1e})",
p.x, p.y);
}
};
然後,傳遞指標物件給任何函式:
point p = {1, 2};
std::string s = fmt::format("{:f}", p);
// s == "(1.0, 2.0)"
還可以通過繼承或組合來重用現有的格式化器,例如:
enum class color {red, green, blue};
template <> struct fmt::formatter<color>: formatter<string_view>
{
// parse is inherited from formatter<string_view>.
template <typename FormatContext>
auto format(color c, FormatContext& ctx)
{
string_view name = "unknown";
switch (c)
{
case color::red: name = "red"; break;
case color::green: name = "green"; break;
case color::blue: name = "blue"; break;
}
return formatter<string_view>::format(name, ctx);
}
};
由於解析是從formatter <string_view>繼承的,因此它將識別所有字串格式規範,例如:
fmt::format("{:>10}", color::blue)
這行程式碼將會返回一個字串:" blue"。
可以為類的層次結構編寫格式化器:
#include <type_traits>
#include <fmt/format.h>
struct A
{
virtual ~A() {}
virtual std::string name() const { return "A"; }
};
struct B : A
{
virtual std::string name() const { return "B"; }
};
template <typename T>
struct fmt::formatter<T, std::enable_if_t<std::is_base_of<A, T>::value, char>> :
fmt::formatter<std::string>
{
template <typename FormatCtx>
auto format(const A& a, FormatCtx& ctx)
{
return fmt::formatter<std::string>::format(a.name(), ctx);
}
};
int main(int argc, char * argv[])
{
B b;
A& a = b;
fmt::print("{}", a); // prints "B"
return 0;
}
3、basic_format_parse_context類
template <typename Char, typename ErrorHandler = detail::error_handler>
class fmt::basic_format_parse_context
解析上下文,由解析的格式字串範圍和用於自動索引的引數計數器組成。
可以將一下型別取別名,用於常見字元型別
Type Definition
format_parse_context basic_format_parse_context<char>
wformat_parse_context basic_format_parse_context<wchar_t>
basic_format_parse_context類類繼承: fmt::detail::error_handler
公有函式:
3.1)、begin
constexpr iterator begin() const
返回一個迭代器,指向要解析的格式字串範圍的開頭
3.2)、end
constexpr iterator end() const
返回一個迭代器,指向要解析的格式字串範圍的結束
3.3)、advance_to
void advance_to(iterator it)
將迭代器前進到it
3.4)、next_arg_id
int next_arg_id()
如果使用手動引數索引,則報告錯誤;否則返回下一個引數索引並切換到自動索引。
3.5)、check_arg_id
void check_arg_id(int)
如果使用自動引數索引,則報告錯誤;否則切換到手動索引。
D、支援輸出迭代器
1、
template <typename OutputIt, typename S, typename... Args>
OutputIt fmt::format_to(OutputIt out, const S &format_str, Args&&... args)
格式化引數,將結果寫入輸出迭代器,並返回超出輸出範圍末尾的迭代器。 例如:
std::vector<char> out;
fmt::format_to(std::back_inserter(out), "{}", 42);
2、
template <typename OutputIt, typename S, typename... Args>
format_to_n_result<OutputIt> fmt::format_to_n(OutputIt out, size_t n, const S &format_str, const Args&... args)
格式化引數,將結果的n個字元寫到輸出迭代器中,並返回總輸出大小和迭代器。
3、結構體:fmt::format_to_n_result
template <typename OutputIt>
struct fmt::format_to_n_result
公有成員:
3.1)、OutputIt out
迭代器指向末尾
3.2)、size_t size
總(未截斷)輸出大小。
E、Literal-based API
fmt/format.h中定義了以下使用者定義的Literal。
1、
detail::udl_formatter<char> fmt::literals::operator""_format(const char *s, size_t n)
使用者定義的Litera等效於fmt :: format()。例如:
using namespace fmt::literals;
std::string message = "The answer is {}"_format(42);
2、
detail::udl_arg<char> fmt::literals::operator""_a(const char *s, size_t)
使用者定義的Litera等效於fmt :: argv()。 例如:
using namespace fmt::literals;
fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
F、實用工具(Utilities)
1、fmt::is_char
template <typename T>
struct fmt::is_cha
判斷T是否為字元型別。 繼承false_type
using fmt::char_t = typedef typename detail::char_t_impl<S>::type
字串的字元型別。
2、 fmt::formatted_size
template <typename... Args>
size_t fmt::formatted_size(string_view format_str, const Args&... args)
返回格式(format_str,args ...)的輸出中的字元數。
3、fmt::to_string
template <typename T>
std::string fmt::to_string(const T &value)
使用型別T的預設格式將value轉換為std :: string。例子:
#include <fmt/format.h>
std::string answer = fmt::to_string(42);
4、 fmt::to_wstring
template <typename T>
std::wstring fmt::to_wstring(const T &value)
使用型別T的預設格式將value轉換為std :: wstring。
5、 fmt::to_string_view
template <typename Char>
basic_string_view<Char> fmt::to_string_view(const Char *s)
返回引數S的字串view.為了向{fmt}新增自定義字串型別支援,過載了函式:to_string_view。例如:
namespace my_ns
{
inline string_view to_string_view(const my_string& s)
{
return {s.data(), s.length()};
}
}
std::string message = fmt::format(my_string("The answer is {}"), 42);
6、fmt::join
template <typename Range>
arg_join<detail::iterator_t<const Range>, detail::sentinel_t<const Range>, char> fmt::join(const Range &range, string_view sep)
返回一個物件,該物件的格式設定range用sep分隔的元素。例如:
std::vector<int> v = {1, 2, 3};
fmt::print("{}", fmt::join(v, ", "));
// Output: "1, 2, 3"
fmt :: join將傳遞的格式說明符應用於range元素:
fmt::print("{:02}", fmt::join(v, ", "));
// Output: "01, 02, 03"
7、fmt::join
template <typename It, typename Sentinel>
arg_join<It, Sentinel, char> fmt::join(It begin, Sentinel end, string_view sep
返回一個物件,該物件使用由sep分隔,格式化迭代器範圍[begin,end)。
8、類 fmt::detail::buffer
具有可選增長能力的連續記憶體緩衝區。它是一個內部類,不應該直接使用,通過 basic_memory_buffer 訪問
公有函式:
8.1)、size
size_t size() const
返回緩衝區的大小
8.2)、capacity
size_t capacity() const
返回此緩衝區的容量
8.3)、data
T *data()
返回一個指向該緩衝區的指標,指標型別與模板T有關
8.4)、resize
void resize(size_t new_size)
調整緩衝區大小。如果T是POD型別,則可能不會初始化新元素。
8.5)、clear
void cLear()
清空buffer
8.6)、reserve
void reserve(size_t new_capacity)
保留至少能夠儲存 new_capacity的元素空間
8.7)、append
template <typename U>
void append(const U *begin, const U *end)
向buffer的末尾追加資料
9、fmt::basic_memory_buffer類
動態增長的記憶體緩衝區,用於帶有可儲存在物件本身中的第一個SIZE元素的型別。
將以下類型別名,用於常見字元型別:
Type Definition
memory_buffer basic_memory_buffer<char>
wmemory_buffer basic_memory_buffer<wchar_t>
例如:
fmt::memory_buffer out;
format_to(out, "The answer is {}.", 42);
字串將輸出到out:
The answer is 42.
可以使用to_string(out)將輸出轉換為std :: string。
該類繼承 fmt::detail::buffer< T >
公有函式:
9.1)、basic_memory_buffer
basic_memory_buffer(basic_memory_buffer &&other)
構造一個fmt :: basic_memory_buffer物件,將另一個物件的內容移動到該物件。
9.2)、basic_memory_buffer
basic_memory_buffer &operator=(basic_memory_buffer &&other)
過載運算子,將物件other的值拷貝到當前物件
受保護函式:
9.3)、grow
void grow(size_t capacity)
擴張buffer的容量以便能容納當前元素數量。
G、系統錯誤
fmt不使用errno向用戶傳達錯誤。但它可呼叫設定errno的系統函式errno。使用者不應對庫函式保留的errno值做任何臆測。
1、類fmt::system_error
class fmt::system_error
作業系統或語言執行時返回的錯誤,例如:檔案開啟的錯誤。該類繼承runtime_error。
公有函式:
1.1)、system_error
template <typename... Args>
system_error(int error_code, string_view message, const Args&... args)
構造一個fmt :: system_error物件,其格式為fmt :: format_system_error(),訊息和傳遞給建構函式的引數將會自動被格式化,類似:fmt::format()。例如:
// This throws a system_error with the description
// cannot open file 'madeup': No such file or directory
// or similar (system message may vary).
const char *filename = "madeup";
std::FILE *file = std::fopen(filename, "r");
if (!file)
throw fmt::system_error(errno, "cannot open file '{}'", filename);
2、fmt::format_system_error函式
void fmt::format_system_error(detail::buffer<char> &out, int error_code, string_view message)
格式化由作業系統或語言執行時返回的錯誤,例如檔案開啟錯誤,例如,以下形式輸出:
<message>: <system-message>
其中,<message>是傳遞的訊息,而<system-message>是與錯誤程式碼相對應的系統訊息。error_code是errno給出的系統錯誤程式碼。如果error_code不是有效的錯誤程式碼(例如-1),則系統訊息可能看起來像“未知錯誤-1”,並且取決於平臺因素。
3、類fmt::windows_error
Windows錯誤類,繼承fmt::system_error
3.1)、public建構函式
template <typename... Args>
windows_error(int error_code, string_view message, const Args&... args)
建立一個 fmt::system_error的物件,物件的格式如下:
<message>: <system-message>
其中,<message>是格式化的訊息,而<system-message>是與錯誤程式碼相對應的系統訊息。error_code是GetLastError給出的Windows錯誤程式碼。如果error_code不是有效的錯誤程式碼(例如-1),則系統訊息將看起來像“錯誤-1”。例如:
// This throws a windows_error with the description
// cannot open file 'madeup': The system cannot find the file specified.
// or similar (system message may vary).
const char *filename = "madeup";
LPOFSTRUCT of = LPOFSTRUCT();
HFILE file = OpenFile(filename, &of, OF_READ);
if (file == HFILE_ERROR)
{
throw fmt::windows_error(GetLastError(),
"cannot open file '{}'",
filename);
}
H、定製分配器
fmt庫支援自定義動態記憶體分配。可以將自定義分配器類指定為fmt :: basic_memory_buffer的模板引數:
using custom_memory_buffer = fmt::basic_memory_buffer<char, fmt::inline_buffer_size, custom_allocator>;
也可以編寫使用自定義分配器的格式化函式:
using custom_string =
std::basic_string<char, std::char_traits<char>, custom_allocator>;
custom_string vformat( custom_allocator alloc,
fmt::string_view format_str,
fmt::format_args args)
{
custom_memory_buffer buf(alloc);
fmt::vformat_to(buf, format_str, args);
return custom_string(buf.data(), buf.size(), alloc);
}
template <typename ...Args>
inline custom_string format(custom_allocator alloc,
fmt::string_view format_str,
const Args& ... args)
{
return vformat(alloc, format_str, fmt::make_format_args(args...));
}
分配器將僅用於輸出容器。如果使用命名引數,則將使用預設分配器分配儲存指向它們的指標的容器。浮點格式還取決於可以進行分配的sprintf。
I、範圍和元組的格式化
該庫還支援範圍和元組的便捷格式化, 例如:
#include <fmt/ranges.h>
std::tuple<char, int, float> t{'a', 1, 2.0f};
// Prints "('a', 1, 2.0)"
fmt::print("{}", t);
注意: 當前的使用的是標頭檔案format.h中的fmt::join函式。
當使用 fmt::join時,可以使用自定義的分隔符將元組的元素分開:
#include <fmt/ranges.h>
std::tuple<int, char> t = {1, 'a'};
// Prints "1, a"
fmt::print("{}", fmt::join(t, ", "));
J、時間和日期的格式化
fmt還支援對時間和日期的格式化處理。
#include <fmt/chrono.h>
std::time_t t = std::time(nullptr);
// Prints "The date is 2016-04-29." (with the current date)
fmt::print("The date is {:%Y-%m-%d}.", fmt::localtime(t));
格式化字串的語法,具體可以 檢視後面的連結: https://en.cppreference.com/w/cpp/chrono/c/strftime
K、編譯時格式化字串
fmt/compile.h提供格式字串編譯支援。格式字串在編譯時進行解析,並轉換為有效的格式程式碼。支援內建和字串型別的引數,以及格式設定專長中具有constexpr解析函式的使用者定義型別的引數。與預設API相比,格式字串編譯可以生成更多的二進位制程式碼,僅在格式化是效能瓶頸的地方才建議使用。
FMT_COMPILE(s)
將字串文字s轉換為格式字串,該格式字串將在編譯時進行解析,並轉換為有效的格式程式碼。如果編譯器支援,則需要C ++ 17 constexpr。例如:
// Converts 42 into std::string using the most efficient method and no
// runtime format string processing.
std::string s = fmt::format(FMT_COMPILE("{}"), 42);
L、標準輸出流std::ostream 的支援
fmt/ostream.h提供std :: ostream支援,包括格式化運算子<<的使用者定義型別的格式。例如:
include <fmt/ostream.h>
class date
{
int year_, month_, day_;
public:
date(int year, int month, int day): year_(year), month_(month), day_(day) {}
friend std::ostream& operator<<(std::ostream& os, const date& d)
{
return os << d.year_ << '-' << d.month_ << '-' << d.day_;
}
};
std::string s = fmt::format("The date is {}", date(2012, 12, 9));
// s == "The date is 2012-12-9"
1、 fmt::print
template <typename S, typename... Args, typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
void fmt::print(std::basic_ostream<Char> &os, const S &format_str, Args&&... args)
將格式化的資料輸出到標準輸出流os。例如:
fmt::print(cerr, "Don't {}!", "panic");
M、printf的格式化
標頭檔案fmt / printf.h提供類似printf的格式化功能。以下函式使用帶有POSIX副檔名的printf格式字串語法來表示位置引數。與標準對等函式不同,fmt函式具有型別安全性,如果引數型別與其格式規範不匹配,則丟擲異常。
1、fmt::printf
template <typename S, typename... Args>
int fmt::printf(const S &format_str, const Args&... args)
將格式化的資料輸出到stdout。例如:
fmt::printf("Elapsed time: %.2f seconds", 1.23);
2、fmt::fprintf
template <typename S, typename... Args, typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
int fmt::fprintf(std::FILE *f, const S &format, const Args&... args)
將格式化的資料輸出到檔案。例如:
fmt::fprintf(stderr, "Don't %s!", "panic");
3、fmt::fprintf
template <typename S, typename... Args, typename Char = char_t<S>>
int fmt::fprintf(std::basic_ostream<Char> &os, const S &format_str, const Args&... args)
將資料輸出到os。 例如:
fmt::fprintf(cerr, "Don't %s!", "panic");
4、fmt::sprintf
template <typename S, typename... Args, typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
std::basic_string<Char> fmt::sprintf(const S &format, const Args&... args)
格式化引數,並返回一個已經格式化的字串。例如:
std::string message = fmt::sprintf("The answer is %d", 42);
N、相容c++20的std::format
fmt幾乎實現了所有c++20中格式化庫,但有幾點不同:
1、名稱空間的不同,fmt的函式全部都在fmt的名稱空間下,避免了與std名稱空間下的函式同名衝突。
2、當前的fmt庫中,'L'仍然不能用做格式化符連線使用。
3、寬度計算不使用字素聚類。後者已在單獨的分支中實施,但尚未整合。
4、計時格式不支援C ++ 20日期型別,因為它們不是標準庫實現提供的。
--------------------------------------完--------------------------------------------------
githu是個好地方,人富水也甜。
歡迎指正