constexpr vs const vs constexpr const

时间:2016-04-04 14:32:23

标签: c++ c++14 constexpr

const-vs-constexpr-on-variables

关于constexpr的人说的是正确的if double(当然还是float)。但是,如果将var类型从double更改为整数类型(如int,char等),则一切正常。为什么会这样?

http://ideone.com/DAWABE

int main() 
{
    const int PI1 = 3;
    constexpr int PI2 = 3;
    constexpr int PI3 = PI1;  // works
    static_assert(PI1 == 3, "");  // works

    const double PI1__ = 3.0;
    constexpr double PI2__ = 3.0;
    constexpr double PI3__ = PI1__;  // error
    static_assert(PI1__ == 3.0, "");  // error
    return 0;
}

Update:以下行是错误的,我的意思是PI3__ = PI1__

constexpr double PI3__ = PI1;  // I meant PI1__

问题:

  1. 为什么const int = 3是编译时常量而const double = 3.0不是?

  2. 我有理由将constexpr const int val;用于constexpr int val吗?他们似乎都完全一样。

3 个答案:

答案 0 :(得分:2)

根据您在评论中的回答,这是我的答案。 C ++标准非常清楚。 GCC 5.1在这里工作得很好:https://godbolt.org/g/2oV6Hk

  

T类型的转换常量表达式是一个表达式,隐式转换为类型T,其中转换后的表达式   expression是一个常量表达式,隐式转换序列只包含   §5.20134   c ISO / IEC N4567

     

[...]

     

(4.6) - 积分促销(4.5),

     

(4.7) - 除了缩小转化次数(8.5.4)之外的积分转换(4.7),

     

[...]

关于缩小n4567中转换率(8.5.4 / 7)的参考:

  

缩小转化是隐式转化

     
      
  • 从浮点类型到整数类型,或
  •   
  • 从long double到double或float,或从double到float,除非source是常量表达式,转换后的实际值在可以表示的值范围内(即使它不能精确表示) ,或
  •   
  • 从整数类型或无范围枚举类型到浮点类型,除非源是常量表达式,转换后的实际值将适合目标类型,并在转换回原始值时生成原始值类型,或
  •   
  • 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,除非source是常量表达式,并且转换后的实际值将适合目标类型并将生成转换回原始类型时的原始值。
  •   

答案 1 :(得分:1)

从评论看来,OP似乎要求标准引用将const int定义为编译时常量,但const double不是。

相应的详细信息可在5.19 Constant Expressions中找到。特别是:

  

......左值到右值的转换(4.1),除非它适用于a   整数或枚举类型的非易失性glvalue,指的是a   具有前面初始化的非易失性const对象,已初始化   一直表达......

int是一个整数类型,而double则不是。

答案 2 :(得分:0)

编译器在初始化constexpr变量时不允许隐式缩小或非整数提升。

这将有效:

int main()
{
    const int PI1 = 3;
    constexpr int PI2 = 3;
    constexpr int PI3 = PI1;  // works
    static_assert(PI1 == 3, "");  // works

    const double PI1__ = 3;
    constexpr double PI2__ = 3;
    constexpr double PI3__ = double(PI1);  // works with explicit cast
    static_assert(PI2__ == 3, "");  // works now. PI1__ isn't constexpr
    return 0;
}