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

时间:2012-02-08 21:37:54

标签: c++ enums c++11 numeric-limits strongly-typed-enum

这里有一些看起来可行的代码:

#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 个答案:

答案 0 :(得分:23)

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

答案 1 :(得分:2)

对于模板的非专业版,max会返回T()。您尚未为numeric_limits类型编写test专门化,因此您将获得默认实施。

答案 2 :(得分:1)

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

您可以自行提供enum规范,将numeric_limits“插入”numeric_limits<test>。您可以从int复制<limits>的{​​{1}},并根据您的需要进行修改。

答案 3 :(得分:1)

来自C ++ 11草案:

在18.3.2.1中,关于numeric_limits

  

非算术标准类型,例如complex(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。