为什么 C++ numeric_limits<enum_type>::max() == 0?

Why is C++ numeric_limits<enum_type>::max() == 0?

本文关键字:max enum numeric C++ limits lt type 为什么 gt      更新时间:2023-10-16

这里有一段看起来可以工作的代码:

#include <cassert>
#include <limits>
enum test { A = 1 };
int main()
{
    int max = std::numeric_limits<test>::max();
    assert(max > 0);
}

但在Linux上,它在GCC(4.6.2)和clang(2.9)下都失败了:枚举类型的max()实际上为零!即使您使用C++11枚举类型说明符来明确说明您希望枚举的类型,这一点仍然正确。

为什么会这样?至于C++11的行为,它是被明确要求的吗?我在N2347这篇关于强类型枚举的论文中没有提到它。

std::numeric_limits在标准库中专门用于"浮点和整数的每种算术类型,包括bool"(§18.3.2.1/2)。

您的枚举test不是这些类型之一,因此使用主模板。其行为由§18.3.2.3/1规定:"默认numeric_limits<T>模板应具有所有成员,但具有0false值。"

如果你想知道test潜在类型的特征,你可以使用underlying_type:

std::numeric_limits<std::underlying_type<test>::type>::max()

或者,您可以将numeric_limits专门化为test,并让它返回您想要的值。不过,这不是一个特别好的主意。

对于模板的非专用版本,max返回T()。您还没有为test类型编写numeric_limits专门化,所以您得到了默认的实现。

numeric_limits<T>是一个常规的类模板,它没有以任何特殊的方式连接到编译器,以了解用户定义的enum类型。如果查看<limits>文件,它有一个默认的模板定义,它对所有内容都返回零,对单个类型有一大堆特定于类型的规范,返回正确的常量。

您可以通过自己提供numeric_limits<test>的规格,将您的enum"插入"到numeric_limits中。您可以从<limits>复制int的一个,并根据需要进行修改。

来自C++11草案:

18.3.2.1中,关于numeric_limits:

非算术标准类型,如复数(26.4.2),不应具有专门化。

枚举不是算术标准类型。

然后,在非专用模板中:

template<class T> class numeric_limits {
    public:
    [...]
    static constexpr bool is_specialized = false;
    static constexpr T max() noexcept { return T(); }
};

也就是说,非专用max()函数返回该类型的默认初始化值,即0。