在常量表达式中使用numeric_limits::max()

30

我想在一个类内部定义一个常量,其值为最大可能的整数。就像这样:

class A
{
    ...
    static const int ERROR_VALUE = std::numeric_limits<int>::max();
    ...
}

这个声明无法通过编译,错误信息如下:

numeric.cpp:8: error: 'std::numeric_limits::max()' cannot appear in a constant-expression numeric.cpp:8: error: a function call cannot appear in a constant-expression

我理解为什么会出现这种情况,但有两点看起来很奇怪:

  1. 在常量表达式中使用该值对我来说似乎是一个自然的决定。为什么语言设计者决定将 max() 设计为函数而不允许这种用法?

  2. 规范在18.2.1中声称:

    对于在numeric_limits模板中声明为static const的所有成员,特化应以可用作整数常量表达式的方式定义这些值。

    这难道不意味着我应该能够在我的场景中使用它吗?这是否与错误消息相矛盾?

谢谢。


1
你可以使用 climits http://www.cplusplus.com/reference/clibrary/climits/。 - Anycorn
1
@aaa:但是 climits 与模板不兼容。 - UncleBens
2
@Uncle 不幸的是,原则上可以将定义包装在模板中,有些工作是可以完成的。或者boost integer_traits提供了它们:integer_traits <>::const_max/const_min - Anycorn
5个回答

17

看起来有点缺陷...

在C++0x中,numeric_limits的所有内容都将标记为constexpr,这意味着您将能够将min()max()用作编译时常量。


对于那些想知道的人,显然在Visual Studio 2015中已经添加了对此的支持。现在如果我能让IT从2013年更新就好了... - Phlucious

16

尽管当前标准不支持此功能,但对于整数类型,Boost.IntegerTraits 提供了编译时常量 const_minconst_max

问题出在 §9.4.2/4 中:

如果静态数据成员是 const 整数或 const 枚举类型,则其在类定义中的声明可以指定一个常量初始化器,该常量初始化器应为整数常量表达式(5.19)。在这种情况下,该成员可以出现在整数常量表达式中。

请注意它补充说:

如果程序中使用了该成员,则仍应在命 名空间范围内定义该成员,并且命名空间范围定义不得包含初始化器。

正如其他人已经提到的,numeric_limitsmin()max() 并不是整数常量表达式,即编译时常量。


14

您想要:

#include <limits>

struct A {
static const int ERROR_VALUE;
}; 

const int A::ERROR_VALUE = std::numeric_limits<int>::max();

将类/结构放在头文件中,定义放在.cpp文件中。

2
上述定义的 ERR_VALUE 可以用作模板参数吗? - Anycorn
2
在类内和类外初始化的区别是什么?我知道我可以在类内使用整数值初始化常量。此外,我必须至少有一个这样的类实例,对吗?否则编译器可能会决定不进行初始化? - FireAphis
跟着问一句:这里没有(也许是boost)重新定义这些值以便在元模板编程中使用的库吗?在编译时拥有它们对我们来说是有意义的... - Matthieu M.
@aaa 不,但那不是他所询问的内容。 - anon
@FireAphis 不需要类实例 - 它是静态的! - anon
1
@Matt http://www.boost.org/doc/libs/1_40_0/boost/integer_traits.hpp 中的 integer_traits<>::const_max 成员是什么意思。@Neil 我只是好奇。 - Anycorn

4
它并不矛盾,因为max没有被定义为static const,它只是一个静态成员函数。函数不能是const,静态成员函数也不能在最右边附加const。
在double版本的限制中也有一个double max(),在C++03中,不能使用static double const max = ...。因此,为了保持一致,max()是所有版本的limit模板的一个函数。
现在已知max()无法像那样使用是不好的,而C++0x通过使其成为constexpr函数来解决这个问题,允许您提出的用法。

2
  • 我会尽力回答你的问题:

1- 如果你想要在程序中使用一个静态常量整数并用函数初始化它:

int Data()
{
 return rand();
}

class A
{
public :
    static const int ee;
};
const int A::ee=Data();

这适用于VS 2008

2- 如果您想要获取给定数据类型的最大和最小数,则可以使用以下定义 INT_MAX,INT_MIN,LONG_MAX等等..

3- 如果您需要针对模板类型使用它们,则需要自己硬编码模板。

template<>
int MaxData()
{
 return INT_MAX;
}

并且。
template<>
long MaxData()
{
 return LONG_MAX ;
}

并且像这样进行调用

int y=MaxData<int>();

4- 如果你只处理二进制表示的类型,请使用以下代码:

template <class T>
T MaxData(){
    return ~(1<<((sizeof(T)*8)-1));
}

并且这个

template <class T>
T MinData(){
    return (1<<((sizeof(T)*8)-1));
}

希望这能帮到您。


不要使用数字值8,而是从climits(limits.h)中使用CHAR_BIT宏。 - Aconcagua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接