2016-01-14 16 views
5

Poniższy program daje mi błąd łącza czas:Posiadanie constexpr statyczny ciąg daje błąd Linker

#include <iostream> 

struct Test { static constexpr char text[] = "Text"; }; 

int main() 
{ 
    std::cout << Test::text << std::endl; // error: undefined reference to `Test::text' 
} 

komunikat o błędzie jest

/tmp/main-35f287.o: In function `main': 
main.cpp:(.text+0x4): undefined reference to `Test::text' 
main.cpp:(.text+0x13): undefined reference to `Test::text' 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

Ok. Spróbujmy ustalić, że: dodać definicję poza ciałem struct:

#include <iostream> 

struct Test { static constexpr char text[] = "Text"; }; 
constexpr char Test::text[] = "Text"; 

int main() 
{ 
    std::cout << Test::text << std::endl; 
} 

Clang daje mi się następujący komunikat o błędzie.

main.cpp:4:35: error: static data member 'text' already has an initializer 
    constexpr char Test::text[] = "Text"; 
           ^
main.cpp:3:50: note: previous initialization is here 
    struct Test { static constexpr char text[] = "Text"; }; 

Och, dobrze, pomyślałem, teraz wiem, co chcesz:

#include <iostream> 

struct Test { static constexpr char text[]; }; 
constexpr char Test::text[] = "Text"; 

int main() 
{ 
    std::cout << Test::text << std::endl; 
} 

i znowu błąd:

main.cpp:3:41: error: declaration of constexpr static data member 'text' requires an initializer 
    struct Test { static constexpr char text[]; }; 

A pies gryzie własny ogon. :(

Czy istnieje sposób na użycie tablic znaków stałych w czasie kompilacji, które są zadeklarowane w klasie? Powodem, dla którego chcę dane w klasie, jest to, że potrzebuję klasy cech typu, która pomaga mi robić szablony .

+0

Czy miałeś na myśli po prostu 'struct Test {static const char text [] =" Text "; }; '? –

+1

Próbowałeś dwóch opcji - inicjalizatora poza klasą, zarówno wewnątrz, jak i na zewnątrz. Teraz jest trzecia alternatywa ... –

+1

Działa to dobrze: 'struct Test {static constexpr auto text =" Text "; }; ' – vincentp

Odpowiedz

8

powinno działać:

#include <iostream> 

struct Test { static constexpr char text[] = "Text"; }; 
constexpr char Test::text[]; 

int main() 
{ 
    std::cout << Test::text << std::endl; 
} 

w standardowych (n4140 §9.4.2/3) można znaleźć:

A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. —end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.

+0

Tylko jedno inicjowanie inicjalizacji. –

+0

Działa dla mnie! Dziękuję Ci! –

2

Jak powiedział w komentarzach, ta wersja działa bez zarzutu:

struct Test { static constexpr auto text = "Text"; }; 

Ale text będzie const char* zamiast char[].

+0

Dlaczego to nie działa, aby wydobyć z niego 'const char [5]'? Mam na myśli, dlaczego jest tak duża różnica? To jest denerwujące. To czyni go niezdatnym do użytku dla moich celów. –