13

下面是一些看起来可行的代码:

#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 中没有提到它。

4

4 回答 4

29

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_limitstest并让它返回您想要的值。不过,这不是一个特别好的主意。

于 2012-02-08T21:43:42.560 回答
3

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

于 2012-02-08T21:43:55.403 回答
1

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

您可以通过自己提供规范来“enum插入”您的内容。您可以从中复制一个 for ,并根据需要对其进行修改。numeric_limitsnumeric_limits<test>int<limits>

于 2012-02-08T21:45:10.607 回答
1

来自 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。

于 2012-02-08T21:49:03.317 回答