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
表示,那么maxint
值可能是2^32-1
,但是maxtest
值是1
。为什么有人想为所有枚举专门化它一次?通常,人们会对这个特定的test
枚举的专门化感兴趣。这里有这不会有什么错吧?我不希望依赖于基础类型。如果可能的话,我们就不需要首先进行专门化。专门化的人大概知道类型的属性,并可以相应地实现数值限制
函数。如果有许多num类型,这将是乏味的,但我不会说这很奇怪。这似乎是一个统一描述枚举属性的不错的结构。危险在于让枚举的定义与相应的数值限制
专门化不同步。@jrok:除了尴尬和可能误导之外?不,没有有问题。@RobKennedy:如果你想获得枚举的特征,请编写一个enum\u traits
,不要定义主模板,并将其专门化为单个枚举。这似乎是对的。这在哪里记录的?似乎不在。查找范围内,@nh2。