2014-10-13 11 views
5

Mam klasy z static const członków, że jestem inicjowanie wewnątrz deklaracji klasy:W jaki sposób in statyczna inicjalizacja statyczna floata różni się od int w C++?

#include <iostream> 

class Foo 
{ 
    public: 
     static const int i = 9; 
     static const float f = 2.9999; 
}; 

int main() 
{ 
    std::cout << Foo::i << std::endl; 
    std::cout << Foo::f << std::endl; 
    return 0; 
} 

Kiedy skompilowane z GCC 4.8.2 z opcją --std=c++11, daje ten błąd kompilacji:

foo.cpp:7:32: error: ‘constexpr’ needed for in-class initialization of static data member ‘const float Foo::f’ of non-integral type [-fpermissive] 
     static const float f = 2.9999; 
           ^

Jak wskazuje komunikat, błąd zniknie, jeśli linia zostanie zmieniona na static constexpr float f = 2.9999;.

Dlaczego in statyczna inicjalizacja statyczna zmiennej zmiennoprzecinkowej może różnić się od zmiennej całkowej? Czy nie są one po prostu wartością o określonej wielkości (liczba bajtów), która jest kopiowana (jak makro) lub do której odnosi się wskaźnik?

Niektóre starsze odpowiedzi na podobne (nie takie same) pytania na temat SO wskazują, że dzieje się tak dlatego, że wyrażenia zmiennoprzecinkowe mogą dawać różne wyniki między kompilowaną maszyną a maszyną wykonawczą (przy założeniu scenariusza krzyżowego kompilacji).

Jednakże:

  1. powyższy kod przypisuje wartość bezpośrednio, nie ma arytmetyczna operacja musi być wykonana, aby obliczyć wartość

  2. mogą istnieć różne wyniki dla wyrażeń całkowych też od jego wyniki niedomiaru i przepełnienia nie są jednoznacznie zdefiniowane na różnych architekturach.

  3. Wreszcie, co za magia constexpr zrobić tutaj, że nie ma tego const? Dlaczego język nie działa po , gdy jest używany? To znaczy, dlaczego innego słowa kluczowego, gdy następujące stwierdzenia działa dobrze, jak C++ kod poza klasą w każdym razie: const int i = 9; const float f = 2.9999;

+0

Nie jestem do końca pewien, dlaczego, ale przed C++ 11 działało tylko dla typów integralnych. C++ 11 zezwala na dowolny typ literalny za pośrednictwem 'constexpr'. – chris

+0

@chris: Dlaczego C++ 11 nie robi po prostu tego, co constexpr robi dla tej instrukcji i robi to dla samej const? Dlaczego należy wymagać od użytkownika użycia nowego słowa kluczowego? –

+0

Czy próbowałeś 'static const float f = 2.9999f'? –

Odpowiedz

1

To tylko ograniczenie języka, i jeden, który został rozwiązany przez wprowadzenie ogólnych wyrażeń stałych .

Od pierwotnego C++, tylko statyczne stałe składowe klasy typu całkowego mogą być inicjowane inline; jest to ograniczenie tego samego typu, co w przypadku parametrów szablonu non-type. Tak więc można połączyć dwa tak:

struct MyTrait { static const int value = 10; }; 

template <int N> struct Foo; 

Foo<MyTrait::value> foo; 

W tym użycia, statyczne stały nie jest odr wykorzystane i nie jest wymagana żadna definicja. Spekuluję, ale mogę sobie wyobrazić, że tego rodzaju użycie było główną intencją umożliwienia inline inicjacji. Dla wszystkich innych typów prawdopodobnie i tak chciałbyś mieć definicję, więc równie dobrze możesz umieścić inicjator w definicji.

Oczywiście nie jest to wymówka i wydaje mi się, że wprowadzenie constexpr ma na celu naprawienie tego pierwotnego ograniczonego umysłu.

+1

W oryginalnym C++ żaden statyczny element klasy nie mógł zostać zainicjowany inline. To innowacja w C++ 98. –

+0

@JamesKanze: Uważam to za "oryginalne" :-) –

+2

Programowałem w C++ prawie 10 lat wcześniej. Pierwszą szeroką specyfikacją byłby pierwszy _ język programowania C++, w 1985 roku. –

Powiązane problemy