这里有一些看起来可行的代码:
#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中找不到它,这是关于强类型枚举的论文。
答案 0 :(得分:23)
std::numeric_limits
专门针对每种算术类型的标准库,包括浮点和整数,包括bool
“(§18.3.2.1/ 2)。
您的枚举test
不是这些类型之一,因此使用主模板。其行为由§18.3.2.3/ 1指定:“默认numeric_limits<T>
模板应包含所有成员,但具有0
或false
值。”
如果您想知道基础类型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。