2016-04-04 42 views
2

const-vs-constexpr-on-variablesconstexpr VS常量VS constexpr常量

什么的家伙说,大约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?他们似乎都完全一样。

+0

你使用哪种编译器? 'static_assert(PI1__ == 3,“”);'不允许sinc'PI1__'不是编译时常量。 – HelloWorld

+0

@HelloWorld我知道这是行不通的。我的问题是为什么改变它为int使它工作。我正在使用GCC 5.1和VS 2015 Update 2. – James

+0

因为通过标准'const int'是一个编译时间常量,但是'const double'不是。 – SergeyA

回答

1

从它似乎是OP的意见是要求标准报价且其定义为不const int的编译时间常数,但const double

相应的细节可以在5.19,Constant Expressions找到。特别是:

...左值到右值,除非它被施加到整型或枚举类型引用到 非易失性const对象的 非易失性glvalue转换(4.1)与前面的初始化,初始化 以恒定表达...

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

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; 
} 
+0

狭窄发生在哪里? – SergeyA

+1

PI1是一个int。 PI3__是双重的。 –

+1

哦,我的。那些讨厌的'__'欺骗了我! – SergeyA

2

基于在评论你的答案,这是我的答案。 C++标准很清楚。 GCC 5.1作品这里相当优良,但:https://godbolt.org/g/2oV6Hk

A转换的类型T的常量表达式是一个表达式,隐式转换为类型T,其中,所述转换 表达式是一个常量表达式和隐式转换序列只包含 § 5.20 134 çISO/IEC N4567

[...]

(4.6) - 积分优惠(4.5),

(4.7) - 积分转换(4.7)比缩小转换(8.5.4)其他,

[...]

对于(用于缩小转换参考8.5。4/7)在n4567:

收缩转换是隐式转换

  • 从浮点类型为整数类型,或者从长双
  • 两倍或浮动,或从double到float,除非源是一个常量表达式,并且转换后的实际值在可以表示的值的范围内(即使不能精确表示),或者从整数类型或非范围枚举中获取
  • 键入浮点类型,除了源i一个常量表达式,并且转换后的实际值将适合目标类型,并在转换回原始类型或从整数类型或非范围枚举类型转换为不能表示所有类型的整数类型时生成原始值原始类型的值,除非源代码是常量表达式,转换后的实际值将适合目标类型,并在转换回原始类型时生成原始值。
+0

我的意思是'PI3__ = PI1__',而不是'PI3__ = P1'。我已经更新了我的问题。我猜的问题是为什么const int是一个编译时间常量,而const double不是编译时间常量。 – James