Cómo declarar constexpr extern?
¿Es posible declarar una variable extern constexpr
y definirla en otro archivo?
Lo intenté pero el compilador da error:
Declaración de
constexpr
variable 'i
' no es una definición
In .h:
extern constexpr int i;
In .cpp:
constexpr int i = 10;
4 answers
No, no puedes hacerlo, esto es lo que dice el estándar (sección 7.1.5):
1 El especificador constexpr se aplicará únicamente a la definición de un variable o plantilla 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 una tipo literal (3.9). Si alguna declaración de una función, función plantilla, o plantilla variable tiene un especificador constexpr, entonces todos sus las declaraciones contendrán el especificador constexpr. [Nota: Un explícito la especialización puede diferir de la declaración de plantilla con respecto al especificador constexpr. No se pueden declarar los parámetros de la función constexpr. - nota final ]
Algunos ejemplos dados por el estándar:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-13 07:56:17
No. Extern constexpr no tiene ningún sentido. Por favor, lea http://en.cppreference.com/w/cpp/language/constexpr
Es decir, el bit " se debe construir inmediatamente o asignarle un valor. "
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-13 07:48:11
Estoy de acuerdo con 'swang' arriba, pero hay una consecuencia. Considere:
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.
Incluido1.hpp
void print1();
Incluido1.cpp
#include "Include1.hpp"
#include "ExternHeader.hpp"
#include "ConstexprHeader.hpp"
#include <iostream>
void print1() {
std::cout << "1: extern = " << &e << ", constexpr = " << &c << "\n";
}
Incluido2.hpp
void print2();
Incluido2.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
ES decir, el constexpr
se asigna dos veces, mientras que el extern
se asigna una vez.
Esto es contradictorio para mí, ya que 'espero' constexpr
estar más optimizado que extern
.
Editar: 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. Sin embargo, como he dicho, me sorprendió cuando me encontré con el comportamiento de constexpr
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-02 05:03:28
Sí algo 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-10 09:33:32