繁体   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