Ich habe zwei gute Ansätze gefunden, integrale Arrays zu Kompilierungszeiten here und here zu initialisieren.Wie initialisiert man ein Fließkomma-Array zur Kompilierzeit?
Leider kann keine zur Initialisierung einer Float-Array direkt konvertiert werden; Ich finde, dass ich in der Template-Metaprogrammierung nicht fit genug bin, um dies durch Trial-and-Error zu lösen.
Lassen Sie mich zunächst einen Anwendungsfall erklären:
constexpr unsigned int SineLength = 360u;
constexpr unsigned int ArrayLength = SineLength+(SineLength/4u);
constexpr double PI = 3.1415926535;
float array[ArrayLength];
void fillArray(unsigned int length)
{
for(unsigned int i = 0u; i < length; ++i)
array[i] = sin(double(i)*PI/180.*360./double(SineLength));
}
Wie Sie sehen können, was die Verfügbarkeit von Informationen geht, dieses Array könnteconstexpr
deklariert werden.
jedoch für den ersten Ansatz verknüpft, die Generatorfunktion f
würde wie folgt aussehen:
constexpr float f(unsigned int i)
{
return sin(double(i)*PI/180.*360./double(SineLength));
}
Und das bedeutet, dass eine Vorlage Argument vom Typ float
benötigt wird. Was nicht erlaubt ist. Die erste Idee, die mir in den Sinn kommt, wäre, den Float in einer int-Variablen zu speichern - den Array-Indizes passiert nichts nach ihrer Berechnung, so dass sie von einem anderen Typ sind als sie sind (solange Byte -Länge ist gleich) ist völlig in Ordnung.
Aber siehe:
constexpr int f(unsigned int i)
{
float output = sin(double(i)*PI/180.*360./double(SineLength));
return *(int*)&output;
}
ist keine gültige constexpr
, da sie mehr als die Rückkehr-Anweisung enthält.
constexpr int f(unsigned int i)
{
return reinterpret_cast<int>(sin(double(i)*PI/180.*360./double(SineLength)));
}
funktioniert auch nicht; obwohl man denken könnte, dass reinterpret_cast
genau das tut, was hier gebraucht wird (nämlich nichts), funktioniert es anscheinend nur auf Zeigern.
Nach dem zweiten Ansatz, die Generatorfunktion würde etwas anders aussehen:
template<size_t index> struct f
{
enum : float{ value = sin(double(index)*PI/180.*360./double(SineLength)) };
};
Mit dem, was ist im Wesentlichen das gleiche Problem: Das ENUM kann nicht von float
Typ sein und der Typ kann nicht als int
maskiert werden.
Nun, auch wenn ich nur das Problem auf dem Weg der „so tun, als die float
ist ein int
“ genähert habe, ich weiß nicht wirklich wie dieser Pfad (abgesehen von nicht in Betrieb). Ich würde viel lieber einen Weg, der tatsächlich behandelt die float
als float
(und würde genauso gut eine double
als double
behandeln), aber ich sehe keine Möglichkeit, um die Art Einschränkung auferlegt umgehen.
Leider gibt es viele Fragen zu diesem Thema, die sich immer auf ganzzahlige Typen beziehen und die Suche nach diesem speziellen Problem überlagern. In ähnlicher Weise berücksichtigen Fragen zum Maskieren eines Typs als dem anderen typischerweise nicht die Einschränkungen einer constexpr
oder Template-Parameter-Umgebung.
Siehe [2][3] und [4][5] usw.
Sie werden nicht viel Glück haben eine 'constexpr' Funktion basiert auf' std :: sin() ', da diese Funktion isn Schaffung‘ t eine "conexpr" -Funktion. Vielleicht sollte es sein, aber ab sofort ist es nicht. –
@ DietmarKühl Es ist ein intrinsischer in einigen Compilern. Außerdem ist die Implementierung der Serienerweiterung nicht so schwierig. – Columbo
Mögliches Duplikat der [Taylor-Reihenentwicklung als constexpr] (http://stackoverflow.com/questions/34216359/taylor-series-expansion-as-constexpr) – Drop