std::numeric_limits 对于不专门化的类型有什么作用?

Enr*_*lis 7 c++ language-lawyer numeric-limits

这段代码编译并运行

#include <limits>
#include <iostream>

struct Foo {
    int x;
};

static_assert(!std::numeric_limits<Foo>::is_specialized);

int main() {
    std::cout << "---" << std::endl;
    std::cout << std::numeric_limits<Foo>::lowest().x << std::endl;
    std::cout << std::numeric_limits<Foo>::min().x << std::endl;
    std::cout << std::numeric_limits<Foo>::max().x << std::endl;
    std::cout << "---" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

它打印

---
0
0
0
---
Run Code Online (Sandbox Code Playgroud)

这些数字从哪里来?

在 cppreference 上我读到了

此信息是通过std::numeric_limits模板的专业化提供的。标准库为所有算术类型提供了专业化

由此我推断,缺乏对给定类型的专门化Foo意味着我不允许将其用于Foo. 那么上面的输出只是UB的一种表现吗?或者是什么?

如果我在上面的代码中更改intchar,则输出为

---
---
Run Code Online (Sandbox Code Playgroud)

这对我来说是“什么?! s 去哪里了std::endl,首先???”

eer*_*ika 6

使用非专业化numeric_limits是明确定义的。该代码示例没有 UB。引用标准草案:

...
static constexpr T min() noexcept { return T(); }
static constexpr T max() noexcept { return T(); }
static constexpr T lowest() noexcept { return T(); }
...
Run Code Online (Sandbox Code Playgroud)

对于numeric_limits主模板,所有数据成员都是值初始化的,并且所有成员函数都返回一个值初始化的对象。

[注 1:这意味着所有成员都有零或false值,除非numeric_limits专门用于某种类型。-尾注]

- [数字.限制.一般] p3


use*_*522 4

std::numeric_limits值初始化所有成员或从成员函数返回值的主要模板,请参阅[numeric.limits.general]/3。如果模板不是专门针对所提供的类型,这就是您得到的结果。没有UB。

任何专业化都应设置is_specializedtrue并且必须定义所有成员,并在适用的情况下使用合理的值,否则0false参阅[numeric.limits.special]/1[numeric.limits.general]/4

有趣的是[numeric.limits.general]/4需要将标准专业化设置为is_specializedtrue但我没有看到用户专业化的任何等效要求。