标签: stdformat

如何在编译时检查所有参数是否有足够的“{}”占位符?

std::format有一个(编译时和运行时)格式字符串验证,但此验证中不包括的一件事是是否有足够的{}占位符用于所有参数(过多的参数将被默默忽略)。

我认为这在某些罕见的情况下可能很有用(例如,如果您生成格式字符串),但我不需要它,并且因此我遇到了一些错误。

我可以做些什么来检查这个编译时间吗?可能通过包装std::format我自己的函数。

例子:

#include <format>
#include <iostream>

int main()
{
    std::cout << std::format("{} {}", 1, 2, 3, 4, 5) << '\n'; // Prints `1 2`, no error!
}
Run Code Online (Sandbox Code Playgroud)

注意: std::format 确实有编译时格式字符串验证。他们只是不检查这个具体问题(过多的争论)。

c++ fmt stdformat

19
推荐指数
1
解决办法
301
查看次数

如何直接使用 std::formatter ?

假设我想std::formatter绕过直接使用 来格式化单个对象std::format。我怎么做?

根据Formatter,我需要调用.format(value, format_ctx),其中format_ctxstd::format_contextor std::basic_format_context<...>。但我如何构建这个上下文呢?

该标准似乎没有提供一种构建方法。查看libstdc++ 源代码, 的成员变量basic_format_context都是私有的,没有非默认构造函数,并且如果不是friend.

这是否意味着std::formatter不可能按设计手动使用?


我为什么要这样做?

我想使用“调试格式”( "{?:}") 来格式化一个值(如果支持的话),回退到常规"{}".

检查支持的方法似乎是requires(std::formatter<T> f){f.set_debug_format();},我想如果我已经直接与格式化程序交互,我不妨只使用格式化程序本身。

c++ fmt stdformat

12
推荐指数
1
解决办法
367
查看次数

运行时 std::format 可能吗?

我可以使用运行时以 std::format 定义的格式字符串吗?

这似乎是在说你不能;所有格式字符串都是编译时的事情。我可以发誓我是在几个月前才这么做的,也许是在标准回归之前。

#include <iostream>
#include <string>
#include <format>

std::string centre(std::string& string, const int width, const char fillchar = ' '){
    if (width <= string.size())
        return string;
    
    string = std::format("|{0:{1}^{2}}|", string, fillchar, width); //line 25
    return string;
}

int main() {
   std::cout << centre(s, 10, '*');
}
Run Code Online (Sandbox Code Playgroud)

在构建时,我收到错误

string.cpp(25,24): 错误 C7595: 'std::_Basic_format_string<char,row::string::str &,const size_t &,const char &>::_Basic_format_string': 对立即函数的调用不是常量表达

c++ c++20 stdformat

7
推荐指数
1
解决办法
2847
查看次数

C++20 格式的异常消息

类似于这个问题。需要使用类似 printf 的风格而不是字符串串联或 iostreams 来抛出异常和消息。使用 C++ 20 格式化库:

  throw std::runtime_error { 
    std::format("Critical error! Code {}: {}", errno, strerror(errno)) 
  }; 
Run Code Online (Sandbox Code Playgroud)

但在所有带有格式化的异常中,感觉调用格式都不符合人体工学,可以变得更好吗?

c++ c++20 stdformat

5
推荐指数
1
解决办法
347
查看次数

为什么 std::format 和 std::vformat 的参数采用转发引用?

我需要在工作中使用std::format这样的上下文:

for(std::size_t i = 0; i < ...; ++i)
{
   std::format("some string {}", i);
}
Run Code Online (Sandbox Code Playgroud)

由于循环变量i作为转发引用传递,自动 linter 会发出警告,表明它是通过引用传递的,并且可能会被修改。

在阅读了 cppreference 和std::format 提案后,似乎Formatter要求允许格式化参数为非常量,但我无法弄清楚为什么,并且草案实际上建议const Args&...参数化而不是Args&&...

作为一个实验,我尝试移动字符串,甚至专门std::formatter针对我自己的类型:

#include <format>
#include <iostream>
#include <string>

struct MyStruct {
    std::string a = "abc";

    MyStruct(){}
    MyStruct(const MyStruct&) { std::cout << "copy ctor" << std::endl; }
    MyStruct(MyStruct&&) noexcept { std::cout << "move ctor" << std::endl; }
    MyStruct& operator=(const MyStruct&) { std::cout << "copy assignment" << …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 stdformat

3
推荐指数
1
解决办法
155
查看次数

使用 std::format_args 解决范围后堆栈使用问题

std::format_args当我尝试与 一起使用时,出现 stack-use-after-scope 错误std::vformat()。重现它的简单代码是:

#include <format>
#include <iostream>
#include <string>

int main() {
    int i = 42;
    std::string s = "hello";
    std::format_args args = std::make_format_args(i, s);
    std::cout << std::vformat("Number: {}, Word: {}", args) << '\n';

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的is变量应该仍然在范围内并且不是右值,所以我不确定是什么触发了错误。如果我删除并直接在调用中args调用to ,一切都会按预期进行。我缺少什么?std::make_format_args()std::vformat()

这是我编译上述代码的命令:clang++-17 --std=c++23 -stdlib=libc++ -fsanitize=address fmt.cpp

c++ address-sanitizer c++20 stdformat

3
推荐指数
1
解决办法
84
查看次数

如何在 C++ 中扩展现有类型(例如 float)的格式规范?

我想扩展浮点类型的格式化选项,最好保留一些现有选项。例如,我想type为带有单位的测量添加一个新的说明符,像这样编写std::format({:.5mm}, 0.05f)并使用 打印我的数据precision=5,但也乘以 1000 并以“mm”为前缀。这可能吗?

c++ c++20 stdformat

1
推荐指数
1
解决办法
70
查看次数

标签 统计

c++ ×7

stdformat ×7

c++20 ×5

fmt ×2

address-sanitizer ×1