C++ 为什么C++;数值限制<;枚举类型>;::max()==0?

C++ 为什么C++;数值限制<;枚举类型>;::max()==0?,c++,enums,c++11,numeric-limits,strongly-typed-enum,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); } #包括 #包括 枚举测试{A=1}; int main() { int max=std::numeric_limits::max();

下面是一段代码,它似乎可以工作:

#include <cassert>
#include <limits>

enum test { A = 1 };

int main()
{
    int max = std::numeric_limits<test>::max();
    assert(max > 0);
}
#包括
#包括
枚举测试{A=1};
int main()
{
int max=std::numeric_limits::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规定:“默认的
数值限制
模板应具有所有成员,但具有
0
false
值。”

如果您想知道
test
的底层类型的特征,可以使用
底层类型

std::numeric_limits<std::underlying_type<test>::type>::max()
std::numeric\u limits::max()

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

对于非专用版本的模板,
max
返回
T()
。您没有为您的
测试
类型编写
数值\u限制
专门化,因此您得到了默认实现。

数值\u限制
是一个常规类模板,它没有以任何特殊方式连接到编译器,以了解用户定义的
枚举
类型。如果查看
文件,它有默认的模板定义,所有内容都返回零,每个类型都有一系列特定于类型的规范,返回正确的常量

您可以通过自己提供
数值\u限制的规范,将
枚举
插入
数值\u限制
。您可以从
中复制
int
的值,并根据需要对其进行修改。

来自C++11草稿:

在18.3.2.1中,关于
数值限制

非算术标准类型,如complex(26.4.2),不应有专门化

枚举不是算术标准类型

然后,在非专用模板中:

template<class T> class numeric_limits {
    public:
    [...]
    static constexpr bool is_specialized = false;
    static constexpr T max() noexcept { return T(); }
};
模板类数值\u限制{
公众:
[...]
静态constexpr bool是_=false;
静态constexpr T max()noexcept{return T();}
};

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

你期望值是什么?什么是专门化的结果?@JamesMcNellis:我假设他期望它与数值极限相同::max.@RaptorFactor:但这不是
测试
对象可表示的最大值。
测试
对象可表示的最大值为
1
@JohnZwinck:您可以检查
是否专用
。如果不是这样,那么所有的值都应该被认为是无意义的。枚举确实不是算术标准类型,但这并不意味着它是非算术标准类型。它根本不是任何一种标准类型。@RobKennedy-噢!你是对的!这一段在这方面毫无意义。但这并没有改变要点:
numeric\u limits
并不是专门针对枚举类型的。@RobKennedy:这充其量是奇怪的,充其量也是误导性的。不能对所有枚举进行一次专门化(因为标准库中有枚举),因此必须对每个单独的枚举进行专门化。那么,这些值应该是什么呢?您不能直接遵从
基础类型,因为基础类型可表示的最大值不一定是枚举可表示的最大值(例如,如果
test
int
表示,那么max
int
值可能是
2^32-1
,但是max
test
值是
1
。为什么有人想为所有枚举专门化它一次?通常,人们会对这个特定的
test
枚举的专门化感兴趣。这里有这不会有什么错吧?我不希望依赖于基础类型。如果可能的话,我们就不需要首先进行专门化。专门化的人大概知道类型的属性,并可以相应地实现
数值限制
函数。如果有许多num类型,这将是乏味的,但我不会说这很奇怪。这似乎是一个统一描述枚举属性的不错的结构。危险在于让枚举的定义与相应的
数值限制
专门化不同步。@jrok:除了尴尬和可能误导之外?不,没有有问题。@RobKennedy:如果你想获得枚举的特征,请编写一个
enum\u traits
,不要定义主模板,并将其专门化为单个枚举。这似乎是对的。这在哪里记录的?似乎不在。查找范围内,@nh2。