簡體   English   中英

fmt::format中如何省略空的arguments?

[英]How to omit the empty arguments in fmt::format?

有沒有辦法在fmt::format function 的參數列表中省略空字符串文字 ( "" )?

我有下面的片段,它給出了所需的 output:

#include <string>
#include <fmt/core.h>


int main( )
{
    const std::string application_layer_text_head { fmt::format( "{:*<5}[Application Layer]{:*<51}\n\n", "", "" ) };
    fmt::print( "{}", application_layer_text_head );
}

Output:

*****[Application Layer]***************************************************

因此,與其寫成這樣: fmt::format( "{:*<5}[Application Layer]{:*<51}\n\n", "", "" )我們可以刪除空文字並寫成這樣: fmt::format( "{:*<5}[Application Layer]{:*<51}\n\n" ) ? 我試過了,但編譯失敗。 這兩個文字並沒有真正起到任何作用,所以我想找到一種不寫它們的方法。

澄清一下,我只想在開頭有 5 *然后是[Application Layer]然后是 51 *然后是 2 \n

格式化標記用於使用用戶提供的一些數據來格式化字符串。 格式中專用語法的細節可以調整此格式的工作方式,甚至可以插入字符等。 但此功能旨在補充基本行為:獲取一些用戶提供的 object 並將其注入字符串。

所以不, format沒有一種機制可以讓你避免提供用戶提供的數據,這是format存在的全部原因。

還應該注意的是,格式說明符中:之后的文本的含義是根據正在格式化的 object 的類型定義的。 “*<5”的意思是“對齊到 5 個字符,使用 '*' 字符填充空白”只是因為您為該特定格式參數提供了一個字符串。 因此, format不僅沒有提供執行此操作的方法,而且在功能上也不能 您必須告訴它正在使用什么類型,因為這是處理“*<5”含義的一個組成部分。

如前所述, format不能做到這一點。 但是您對字符串連接成本高昂的擔憂是錯誤的。 operator+的重復應用是昂貴的(執行新分配,復制所有現有數據和新數據,丟棄舊數據,一遍又一遍),但是與operator+=append的就地連接是便宜的,特別是如果你reserve (所以你預先分配一次並填充,而不是依靠重新分配中的攤銷增長模式來拯救你)。 即使沒有reservestd::string也遵循分攤增長模式,因此重復的就地連接分攤為O(1) (每個添加的字符),而不是目前數據大小的O(n)

根據定義,以下內容應該至少與格式化一樣快,盡管以大量代碼行為代價來執行預reserve以防止重新分配:

#include <string>
#include <string_view>
#include <fmt/core.h>

using namespace std::literals;

int main( )
{
    // Make empty string, and reserve enough space for final form
    auto application_layer_text_head = std::string();
    application_layer_text_head.reserve(5 + "[Application Layer]"sv.size() + 51 + "\n\n"sv.size());

    // append is in-place, returning reference to original string, so it can be chained
    // Using string_view literals to avoid need for any temporary runtime allocated strings,
    // while still allowing append to use known length concatenation to save scanning for NUL
    application_layer_text_head.append(5, '*').append("[Application Layer]"sv).append(51, '*').append("\n\n"sv);
    fmt::print("{}", application_layer_text_head);
}

如果您對某些可能執行重新分配的串聯以及將資源從臨時引用移動到真實字符串的最終移動構造表示滿意,它會簡化為單行代碼:

const auto application_layer_text_head = std::move(std::string(5, '*').append("[Application Layer]"sv).append(51, '*').append("\n\n"sv));

或者,考慮到 5 個星號足夠短,可以輸入更短/更簡單的版本:

const auto application_layer_text_head = std::move("*****[Application Layer]"s.append(51, '*').append("\n\n"sv));

但是將它保持為兩行可以避免移動構造並且更安全一些:

auto application_layer_text_head = "*****[Application Layer]"s;
application_layer_text_head.append(51, '*').append("\n\n"sv);

是的,這些都沒有單一格式文字那么漂亮,即使有“丑陋”的空占位符。 如果您更喜歡格式字符串的外觀,只需像您已經在做的那樣傳遞空占位符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM