【问题标题】:Using numeric_limits::max() in constant expressions在常量表达式中使用 numeric_limits::max()
【发布时间】:2011-02-13 20:53:46
【问题描述】:

我想在一个类中定义一个常量,它的值是最大可能的 int。像这样的:

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

此声明无法编译并显示以下消息:

numeric.cpp:8: error: 'std::numeric_limits::max()' 不能出现在常量表达式中 numeric.cpp:8:错误:函数调用不能出现在常量表达式中

我明白为什么这不起作用,但有两件事在我看来很奇怪:

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

  2. 规范在 18.2.1 中声称

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

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

谢谢。

【问题讨论】:

  • @aaa:但是climits 不能很好地处理模板。
  • @Uncle 很不幸。原则上可以将定义包装在模板中,有些工作但可行。或提升 integer_traits 我认为已经提供了它们:integer_traits &lt;&gt;::const_max/const_min

标签: c++ std constexpr numeric-limits


【解决方案1】:

看起来有点瑕疵...

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

【讨论】:

  • 对于那些想知道的人,显然在 Visual Studio 2015 中添加了对此的支持。现在,如果我能让 IT 从 2013 年更新...
【解决方案2】:

虽然目前的标准在这里缺乏支持,但对于整数类型 Boost.IntegerTraits 为您提供编译时常量 const_minconst_max

问题出自§9.4.2/4

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

请注意,它添加了:

如果在程序中使用该成员,则该成员仍应在名称空间范围内定义,并且名称空间范围定义不应包含初始值设定项。

正如其他人已经提到的那样,numeric_limits min()max() 根本不是整数常量表达式,即编译时常量。

【讨论】:

    【解决方案3】:

    你想要:

    #include <limits>
    
    struct A {
    static const int ERROR_VALUE;
    }; 
    
    const int A::ERROR_VALUE = std::numeric_limits<int>::max();
    

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

    【讨论】:

    • 如上定义的 ERR_VALUE 能否用作模板参数?
    • 类内初始化和类外初始化有什么区别?我知道我可以用整数值在类中初始化 const。另外,我必须至少有一个这样的类的实例,对吧?否则编译器可能决定不初始化它?
    • 标记:这里没有任何库(也许是提升)重新定义这些值,以便它们可以在元模板编程中使用?在编译时让它们供我们使用是有意义的......
    • @aaa 不,但这不是他要问的。
    • @Matt boost.org/doc/libs/1_40_0/boost/integer_traits.hpp integer_traits::const_max 成员做到了。 @Neil 我只是好奇
    【解决方案4】:

    这并不矛盾,因为max 没有定义static const。它只是一个静态成员函数。函数不能是 const,静态成员函数也不能在最右边附加 const。

    还有一个double max()在double版本的limits中,在C++03中说static double const max = ...是行不通的。为了保持一致,max() 是一个适用于所有版本的限制模板的函数。

    现在,众所周知,max() 不能像那样使用是很糟糕的,而 C++0x 已经通过将其设置为 constexpr 函数来解决它,从而允许您建议的用法。

    【讨论】:

      【解决方案5】:
      • 我会尽量回答你的问题:

      1- 如果您希望程序中的静态 const int 使用函数进行初始化:

      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- 但是,如果您需要使用这些 wrt 模板类型,那么 自己对模板进行硬编码

      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 宏。
      猜你喜欢
      • 2014-07-04
      • 1970-01-01
      • 2020-05-01
      • 2012-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多