Krótka odpowiedź jest taka, że nie tylko jest static
przydatna, ale też całkiem dobrze będzie zawsze pożądana.
Po pierwsze, zauważ to static
i constexpr
są całkowicie od siebie niezależne. static
określa czas życia obiektu podczas wykonywania; constexpr
określa, że obiekt powinien być dostępny podczas kompilacji. Kompilacja i wykonanie są rozłączne i niejednoznaczne, zarówno w czasie, jak i przestrzeni. Po skompilowaniu program constexpr
przestaje być istotny.
Każda zadeklarowana zmienna constexpr
jest domyślnie, const
ale const
i static
prawie ortogonalna (z wyjątkiem interakcji z static const
liczbami całkowitymi).
Model C++
obiektowy (§ 1.9) wymaga, aby wszystkie obiekty inne niż pola bitowe zajmowały co najmniej jeden bajt pamięci i miały adresy; ponadto wszystkie takie obiekty, które w danym momencie można zaobserwować w programie, muszą mieć odrębne adresy (pkt 6). Nie wymaga to od kompilatora utworzenia nowej tablicy na stosie dla każdego wywołania funkcji z lokalną niestatyczną stałą tablicą const, ponieważ kompilator może schronić się w as-if
zasadzie, pod warunkiem, że może udowodnić, że żaden inny taki obiekt nie może być zauważony.
Niestety nie będzie to łatwe do udowodnienia, chyba że funkcja jest trywialna (na przykład nie wywołuje żadnej innej funkcji, której treść nie jest widoczna w jednostce tłumaczenia), ponieważ tablice, mniej więcej z definicji, są adresami. Dlatego w większości przypadków const(expr)
tablica niestatyczna będzie musiała zostać odtworzona na stosie przy każdym wywołaniu, co nie pozwala na obliczenie jej w czasie kompilacji.
Z drugiej strony, static const
obiekt lokalny jest wspólny dla wszystkich obserwatorów, a ponadto może zostać zainicjowany, nawet jeśli funkcja, w której jest zdefiniowany, nigdy nie zostanie wywołana. Żadne z powyższych postanowień nie ma zastosowania, a kompilator może nie tylko wygenerować tylko jedną jego instancję; wygenerowanie pojedynczego wystąpienia w pamięci tylko do odczytu jest bezpłatne.
Więc zdecydowanie powinieneś użyć static constexpr
w swoim przykładzie.
Jest jednak jeden przypadek, w którym nie chcesz używać static constexpr
. O ile constexpr
zadeklarowany obiekt nie jest używany ani deklarowany ODRstatic
, kompilator może go w ogóle nie uwzględniać. Jest to bardzo przydatne, ponieważ pozwala na użycie tymczasowych constexpr
tablic w czasie kompilacji bez zanieczyszczania skompilowanego programu niepotrzebnymi bajtami. W takim przypadku najwyraźniej nie chcesz używać static
, ponieważ static
prawdopodobnie zmusi obiekt do istnienia w czasie wykonywania.
const
zconst
obiektu, jedynie zconst X*
którego punkty doX
. Ale nie o to chodzi; chodzi o to, że obiekty automatyczne nie mogą mieć adresów statycznych. Jak powiedziałem,constexpr
przestaje mieć znaczenie po zakończeniu kompilacji, więc nie ma nic do odrzucenia (i całkiem możliwe, że w ogóle, ponieważ nie można zagwarantować, że obiekt istnieje w środowisku wykonawczym.)