【发布时间】:2020-11-20 15:51:06
【问题描述】:
C++20 引入了以下format 函数(locale 和 wstring_view 版本被忽略,因为它们不影响问题):
template<class... Args>
std::string format(std::string_view fmt, const Args&... args);
这没有错,但我想知道为什么没有接受“强类型定义”的重载,比如
template<class... Args>
std::string format(std::format_string fmt, const Args&... args);
我的猜测是以下部分或全部:
-
增加了实现的复杂性
-
增加编译时间
-
代码膨胀
,但我想知道在标准化过程中是否讨论过这个问题。
【问题讨论】:
-
因为根据您的提议,
"Bob"肯定是一个有效的format_string,而"Hi, {}"是一个有效的std::string,我能看到这个工作的唯一方法是如果你 禁用 第一次重载并强制人们将他们的格式字符串转换为std::format_string以调用format。我想您可能会争辩说,使用比格式字符串接受的更多参数调用std::format应该是一个错误,但在典型的使用场景下这仍然是一个 runtime 错误。 -
那么,究竟是什么会阻止
"Bob"以不允许std::format("Bob", "Hi, {}")的方式转换为std::format_string? -
如果您依赖显式构造函数来阻止调用
std::format("Bob", "Hi, {}"),这意味着您将禁用std::format的重载,该重载将std::string_view作为其第一个参数。此时 neitherstd::format("Bob", "Hi, {}")norstd::format("Hi, {}", "Bob")是一个有效的调用,因为没有一个std::format_string作为第一个参数。但如果你真的将它们存储在变量std::format_string fs("Hello {}"); std::string name("Bob"); std::format(name, fs)中就行不通了? -
如果您的目标不是阻止
std::format("Bob", "Hello, {}")编译,那么很难看出它实际上做了什么。如果问题是您自己的函数当前具有签名foo(std::string, std::string),并且您想将它们重写为foo(format_string, std::string)以尝试强制执行顺序,您可以在std::string周围编写自己的瘦包装器。 -
@NathanPierson:“我想让用户能够避免在他们的代码中编译这样的代码(如果他们强制使用 format_string)。”但是你'重新建议不会这样做,因为这些都不是
format_strings。它们是字符串文字。