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
No. Extern constexpr no tiene ningún sentido. Lea http://en.cppreference.com/w/cpp/language/constexpr
es decir, el bit "debe construirse inmediatamente o asignarse un valor".
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;
}