Nach der Antwort using boost math constants in constexpr und OP vorschlagen Boost Templated Funktion für eine constexpr
Variable anstelle der nicht-templated-Konstante, um einen Clang Fehler unterdrücken, entschied ich zu versuchen, um zu sehen, welche Bedingungen würde den Fehler in clang reproduzieren. Lassen Sie uns versuchen Makro zu kopieren, was Auftrieb des expandiert nach:clang 3.5 consExpr Inkonsistenz - Fehler bei der Verwendung von double aber nicht int
namespace double_constants{ static const double name = 25; }
static constexpr double SEC3 = double_constants::name;
Das folgende Fehler gibt (folgen zusammen auf Coliru)
clang++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:5:25: error: constexpr variable 'SEC3' must be initialized by a constant expression
static constexpr double SEC3 = double_constants::name;
^ ~~~~~~~~~~~~~~~~~~~~~~
main.cpp:5:32: note: read of non-constexpr variable 'name' is not allowed in a constant expression
static constexpr double SEC3 = double_constants::name;
^
main.cpp:3:49: note: declared here
namespace double_constants{ static const double name = 25; }
Das ist in Ordnung, wir erwartet. Jetzt ändern double
zu int
:
namespace double_constants{ static const int name = 25; }
static constexpr double SEC3 = double_constants::name;
kein Fehler? Unnötig zu sagen, dass ich verwirrt bin. Ich nahm an, der Fehler war, weil die Variable als const
anstelle von constexpr
definiert ist, es sei denn, ich vermisse etwas. Lassen Sie uns einen Blick auf cppreference nehmen:
A constexpr Variable, die die folgenden Anforderungen erfüllen:
- es muss sofort einen Wert konstruiert oder zugeordnet werden.
- Die Konstruktorparameter oder der zuzuweisende Wert darf nur Literalwerte, consExpr-Variablen und Funktionen enthalten.
Wenn wir dies wörtlich zu interpretieren waren, dann klappern in geben einen Fehler gerechtfertigt, weil name
nur const
ist, nicht constexpr
. Und anscheinend double
ist ein LiteralType
weil:
std::cout << std::is_literal_type<double>::value;
Ausgänge 1
. Warum hört sich der Klang dann nicht mehr an, wenn name
int
ist und kein double
?
S.S .: Kann nicht auf gcc reproduzieren.
Zur Verdeutlichung ist das Schlüsselwort static
orthogonal zum Problem. So ist das namespace
. Von dem, was ich verstehe, wickelt das Boost-Makro nicht die static const
Variable in einer Klasse, sondern in einem namespace
. Ich habe es verengt diesen vier Fällen:
// Does not compile
const double name = 25;
constexpr int SEC3 = name;
const double name = 25;
constexpr double SEC3 = name;
// Compiles
const int name = 25;
constexpr double SEC3 = name;
const int name = 25;
constexpr int SEC3 = name;
Ich kann unmöglich static
in jeder Permutation anzuwenden gestört werden kann, um zu sehen, ob es einen Unterschied macht, aber ich bezweifle es tut.
Dies ist ein GCC-Fehler: http://gcc.gnu.org/PR57979 –
Die Anweisung {statische const double name = 25;} generiert eine Gleitkommavariable im Speicher, die nur zur Laufzeit aufgelöst werden kann. Sie können es daher nicht einem conexpr zuweisen, der zur Kompilierungszeit aufgelöst werden muss. Allerdings generiert {static const int name = 25;} eine Variable, die entweder bei der Kompilierung oder der Laufzeit aufgelöst werden kann. Das Zuordnen zu einem Constexpr ist erlaubt. Eigentlich hat gcc den Fehler, nicht klingeln. – coder
statisch macht einen Unterschied in Klassen wie in Klasse A {statisch const int name = 32; }; Kompiliert, aber Klasse A {statisch const double name = 32; }; wird nicht. – coder