and c++ extern constexpr

c++ - and - ¿Cómo declarar constexpr extern?



constexpr in c++ (4)

¿Es posible declarar una variable extern constexpr y definirla en otro archivo?

Lo intenté pero el compilador da error:

Declaración de la variable constexpr '' i '' no es una definición

en .h:

extern constexpr int i;

en .cpp:

constexpr int i = 10;


Estoy de acuerdo con ''swang'' arriba, pero hay una consecuencia. Considerar:

ExternHeader.hpp

extern int e; // Must be extern and defined in .cpp otherwise it is a duplicate symbol.

ExternHeader.cpp

#include "ExternHeader.hpp" int e = 0;

ConstexprHeader.hpp

int constexpr c = 0; // Must be defined in header since constexpr must be initialized.

Include1.hpp

void print1();

Include1.cpp

#include "Include1.hpp" #include "ExternHeader.hpp" #include "ConstexprHeader.hpp" #include <iostream> void print1() { std::cout << "1: extern = " << &e << ", constexpr = " << &c << "/n"; }

Include2.hpp

void print2();

Include2.cpp

#include "Include2.hpp" #include "ExternHeader.hpp" #include "ConstexprHeader.hpp" #include <iostream> void print2() { std::cout << "2: extern = " << &e << ", constexpr = " << &c << "/n"; }

main.cpp

#include <iostream> #include "Include1.hpp" #include "Include2.hpp" int main(int argc, const char * argv[]) { print1(); print2(); return 0; }

Que imprime:

1: extern = 0x1000020a8, constexpr = 0x100001ed0 2: extern = 0x1000020a8, constexpr = 0x100001ed4

IE el constexpr se asigna dos veces mientras que el extern se asigna una vez. Esto es contradictorio para mí, ya que "espero" que constexpr esté más optimizado que extern .

Edit: const y constexpr tienen el mismo comportamiento, con respecto a la asignación, por lo tanto, desde ese punto de vista, el comportamiento es el esperado. Aunque, como dije, me sorprendió cuando me encontré con el comportamiento de constexpr .


No, no puedes hacerlo, esto es lo que dice la norma (sección 7.1.5):

1 El especificador constexpr se aplicará solo a la definición de una variable o plantilla de variable, la declaración de una función o plantilla de función o la declaración de un miembro de datos estáticos de un tipo literal (3.9). Si alguna declaración de una función, plantilla de función o plantilla de variable tiene un especificador constexpr, todas sus declaraciones contendrán el especificador constexpr. [Nota: una especialización explícita puede diferir de la declaración de plantilla con respecto al especificador constexpr. Los parámetros de la función no pueden ser declarados constexpr. - nota final]

Algunos ejemplos dados por la norma:

constexpr void square(int &x); // OK: declaration constexpr int bufsz = 1024; // OK: definition constexpr struct pixel { // error: pixel is a type int x; int y; constexpr pixel(int); // OK: declaration }; extern constexpr int memsz; // error: not a definition



Sí, de alguna manera es ...

//=================================================================== // afile.h #ifndef AFILE #define AFILE #include <cstddef> #include <iostream> enum class IDs { id1, id2, id3, END }; // This is the extern declaration of a **constexpr**, use simply **const** extern const int ids[std::size_t(IDs::END)]; // These functions will demonstrate its usage template<int id> void Foo() { std::cout << "I am " << id << std::endl; } extern void Bar(); #endif // AFILE //=================================================================== // afile.cpp #include "afile.h" // Here we define the consexpr. // It is **constexpr** in this unit and **const** in all other units constexpr int ids[std::size_t(IDs::END)] = { int(IDs::id1), int(IDs::id2), int(IDs::id3) }; // The Bar function demonstrates that ids is really constexpr void Bar() { Foo<ids[0] >(); Foo<ids[1] + 123>(); Foo<ids[2] / 2 >(); } //=================================================================== // bfile.h #ifndef BFILE #define BFILE // These functions will demonstrate usage of constexpr ids in an extern unit extern void Baz(); extern void Qux(); #endif // BFILE //=================================================================== // bfile.cpp #include "afile.h" // Baz demonstrates that ids is (or works as) an extern field void Baz() { for (int i: ids) std::cout << i << ", "; std::cout << std::endl; } // Qux demonstrates that extern ids cannot work as constexpr, though void Qux() { #if 0 // changing me to non-0 gives you a compile-time error... Foo<ids[0]>(); #endif std::cout << "Qux: ''I don''t see ids as consexpr, indeed.''" << std::endl; } //=================================================================== // main.cpp #include "afile.h" #include "bfile.h" int main(int , char **) { Bar(); Baz(); Qux(); return 0; }