Having a static string constexpr gives a linker error

The following program gives me a link time error:

#include <iostream> struct Test { static constexpr char text[] = "Text"; }; int main() { std::cout << Test::text << std::endl; // error: undefined reference to `Test::text' } 

Error message

 /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 Try to fix this: I am adding a definition outside the body of the struct :

 #include <iostream> struct Test { static constexpr char text[] = "Text"; }; constexpr char Test::text[] = "Text"; int main() { std::cout << Test::text << std::endl; } 

Clang gives me the following error message.

 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"; }; 

Oh, well, I thought, now I know what you want:

 #include <iostream> struct Test { static constexpr char text[]; }; constexpr char Test::text[] = "Text"; int main() { std::cout << Test::text << std::endl; } 

And again the error:

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

And there the dog bites its own tail. :(

Is there a way to use persistent compilation-time character arrays declared inside a class? The reason I want the data inside the class is because I need a class of type attributes that helps me create template material.

+5
source share
2 answers

Must work:

 #include <iostream> struct Test { static constexpr char text[] = "Text"; }; constexpr char Test::text[]; int main() { std::cout << Test::text << std::endl; } 

In the standard (n4140 ยง9.4.2 / 3) you can find:

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

+8
source

As stated in the comments, this version works fine:

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

But text will be const char* instead of char[] .

+2
source

Source: https://habr.com/ru/post/1240621/


All Articles