2014-02-10 5 views
8

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 nameint 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.

Antwort

6

Es ist kein Fehler. Leider hat der C++ - Standard verschiedene statische/nicht-statische const-Regeln für Gleitkommatypen und Integertypen.Bitte beachten Sie:

Why aren't static const floats allowed?

Versuchen constexpr statt const wie in:

namespace double_constants{ constexpr double name = 25; } 

und:

constexpr double name = 25; 
constexpr int SEC3 = name; 

Dann sollte es funktionieren.

+4

Dies ist ein GCC-Fehler: http://gcc.gnu.org/PR57979 –

+0

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

+0

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

Verwandte Themen