2016-12-14 44 views
10

Poniższy kod nie skompilować live on Ideone:Inicjowanie constexpr z const: różne traktowanie int i double

#include <iostream> 
using namespace std; 

int main() { 
    const double kPi = 3.14; 
    constexpr double kPi2 = 2.0*kPi; 
    cout << kPi2; 
} 

Komunikat o błędzie jest:

prog.cpp: In function 'int main()': 
prog.cpp:6:30: error: the value of 'kPi' is not usable in a constant expression 
    constexpr double kPi2 = 2.0*kPi; 
          ^
prog.cpp:5:15: note: 'kPi' was not declared 'constexpr' 
    const double kPi = 3.14; 

Podstawiając deklarację const dla kPi z constexpr, it compiles successfully.

Z drugiej strony, gdy int jest używany zamiast double, wydaje się constplays well z constexpr:

#include <iostream> 
using namespace std; 

int main() { 
    const int k1 = 10; 
    constexpr int k2 = 2*k1; 
    cout << k2 << '\n'; 
    return 0; 
} 

Dlaczego int i double uzyskać różne zabiegi dla inicjalizacji constexpr z const?
Czy jest to błąd w kompilatorze Ideone? Czy jest to wymagane przez standard C++? Dlaczego?
Czy powyższy kod był UB?

P.S. Próbowałem z kompilatorem Visual Studio 2015 C++ i kompilował pierwszy fragment kodu (inicjowanie constexpr z const).

+2

[Wydanie 1826: const zmiennoprzecinkowych w stałych wyrażeniach] (http://stackoverflow.com/a/30742473/1708801) obejmuje część historii, dlaczego zmiennoprzecinkowe jest traktowane inaczej. Również [interesujący przestarzały dodatek gcc] (http://stackoverflow.com/q/32813953/1708801). –

+0

@ShafikYaghmour Dzięki. Przegłosowałem ten post. –

+0

Wygląda na to, że komentarz @ ShafikYaghmour powinien być promowany do odpowiedzi, a następnie zaakceptowany. – TriskalJM

Odpowiedz

-3

Reguła: "constexpr musi być oceniony na czas kompilacji".

Spójrzmy poniżej kodu (ogólny przykład);

const double k1 = size_of_array(); 

k1 jest stała, wartość jego inicjator nie jest znana czas kompilacji ale jego inicjator jest znany aż do czasu run k1 tak nie jest stałym wyrażeniem. W rezultacie zmienna const nie jest constexpr.

Ale kompilator zobaczyć te kod:

const int k1 = 10; 
    constexpr int k2 = 2*k1; 

Jeden wyjątek występuje. Wartość integralna constexpr może być używana wszędzie tam, gdzie wymagana jest liczba całkowita, na przykład w argumentach szablonu i deklaracjach tablicowych[1].

Można uzyskać dodatkowe informacje z poniższych linków:

  1. Constexpr - Generalized Constant Expressions in C++11
  2. const vs constexpr on variables | stackoverflow
  3. Difference between constexpr and const | stackoverflow
+0

To nie odpowiada na pytanie, które było o "const double k1 = 3.14;" a nie o "const double k1 = size_of_array();" –

+0

Oczywiście ** double k1 = size_of_array(); ** nie zawiera pytanie ale dałem przykład ** czasu kompilacji ** i ** inicjalizacji runtime ** o wartości const. I ten przykład o każdej zmiennej stałej nie constexpr (wyrażenie stałe). I odpowiedź na to pytanie po tej danej informacji: Wartość integralną constexpr może być użyta wszędzie tam, gdzie wymagana jest liczba całkowita, na przykład w szablonach i deklaracjach tablicowych. [MSDN] (https://msdn.microsoft.com/en-us /library/dn956974.aspx) – straceX

+0

To pytanie dotyczy inicjowania wartości w czasie kompilacji, nie ma znaczenia dla przykładu dotyczącego inicjowania w czasie wykonywania. Twoja odpowiedź sprawia, że ​​problem z kodem OP polega na inicjowaniu środowiska wykonawczego. –

0

Shafik Yaghmour już dostarczono link explaining the background.

Ponieważ mam do utrzymania kod, który ma kompilować z różnymi standardami, używam następujące makro:

#if __cplusplus <= 199711L // lower than C++11 
    #define MY_CONST const 
#else // C++11 and above 
    #define MY_CONST constexpr 
#endif