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 确实有编译时格式字符串验证。他们只是不检查这个具体问题(过多的争论)。
假设我想std::formatter绕过直接使用 来格式化单个对象std::format。我怎么做?
根据Formatter,我需要调用.format(value, format_ctx),其中format_ctx是std::format_contextor std::basic_format_context<...>。但我如何构建这个上下文呢?
该标准似乎没有提供一种构建方法。查看libstdc++ 源代码, 的成员变量basic_format_context都是私有的,没有非默认构造函数,并且如果不是friend.
这是否意味着std::formatter不可能按设计手动使用?
我为什么要这样做?
我想使用“调试格式”( "{?:}") 来格式化一个值(如果支持的话),回退到常规"{}".
检查支持的方法似乎是requires(std::formatter<T> f){f.set_debug_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': 对立即函数的调用不是常量表达
类似于这个问题。需要使用类似 printf 的风格而不是字符串串联或 iostreams 来抛出异常和消息。使用 C++ 20 格式化库:
throw std::runtime_error {
std::format("Critical error! Code {}: {}", errno, strerror(errno))
};
Run Code Online (Sandbox Code Playgroud)
但在所有带有格式化的异常中,感觉调用格式都不符合人体工学,可以变得更好吗?
我需要在工作中使用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) 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)
我的i和s变量应该仍然在范围内并且不是右值,所以我不确定是什么触发了错误。如果我删除并直接在调用中args调用to ,一切都会按预期进行。我缺少什么?std::make_format_args()std::vformat()
这是我编译上述代码的命令:clang++-17 --std=c++23 -stdlib=libc++ -fsanitize=address fmt.cpp。
我想扩展浮点类型的格式化选项,最好保留一些现有选项。例如,我想type为带有单位的测量添加一个新的说明符,像这样编写std::format({:.5mm}, 0.05f)并使用 打印我的数据precision=5,但也乘以 1000 并以“mm”为前缀。这可能吗?