2016-04-08 11 views
4

Ich möchte eine Nachschlagetabelle zur Kompilierzeit für eine mathematische Funktion in einem bestimmten Bereich berechnen und dann Werte aus der Tabelle zur Laufzeit abrufen. Mein Code ist wie folgt:consExpr - Funktion kann nicht in einem konstanten Ausdruck verwendet werden

#include <iostream> 
#include <cmath> 


template<int size> 
class LookupTable { 
public: 
constexpr LookupTable(double xMin, double xMax) : array(), xMin(xMin), xMax(xMax), dx((xMax - xMin)/(size - 1)) { 
    for(auto i = 0; i < size; ++i) 
     array[i] = exp(xMin + i * dx); 
} 

constexpr double operator()(double x) const { 
    return array[std::min(std::max(static_cast<int>((x - xMin)/dx), 0), size-1)]; 
} 

private: 
double array[size]; 
double xMin; 
double xMax; 
double dx; 
}; 



int main() { 
    const double x = 0.5; 
    constexpr LookupTable<10000> table(0.0, 1.0); 
    std::cout << "f(x) = " << table(x) << std::endl; // evaluated at compile time ? 
    std::cout << "f(x) = " << LookupTable<10000>(0.0, 1.0)(x) << std::endl; // evaluated at run time ? 
    return 0; 
} 

Der Code kompiliert und läuft auf gcc 5.1 und höher, aber nicht auf Clang 3.8. Clangs Fehlermeldungen sind: constexpr Variable 'Tabelle' muss durch einen konstanten Ausdruck initialisiert werden und non-constexpr Funktion 'exp' kann nicht in einem konstanten Ausdruck verwendet werden.

Wenn ich die constexpr in entfernen:

constexpr LookupTable<10000> table(0.0, 1.0); 

dann kompiliert den Code und läuft auf Clang auch.

Meine Fragen sind:

  • Was ist die Bedeutung der Fehlermeldung „Funktion‚exp‘in einem konstanten Ausdruck verwendet werden kann, nicht“ ist? Und gibt es einen Workaround?
  • Bedeutet das, wenn ich LookupTable < 10000 deklariere> Tabelle (0.0, 1.0); Ohne den consExpr, dann finden die Tabellenvorberechnungen zur Laufzeit statt? Ich verwende ein Online-Kompilierungstool, daher habe ich keine Option, den Code jetzt zu benchmarken.
  • Ich möchte den Code verallgemeinern und die mathematische Funktion templatisieren. Es funktioniert gut mit Funktoren, aber ist es möglich, Lambdas zu verwenden?

Dank

Antwort

6

Dies scheint seit exp() eine nicht-konforme Erweiterung von gcc zu sein wird, ohne constexpr in <cmath> erklärt:

17.6.5.6 constexpr Funktionen und Konstrukteuren [constexpr.functions]

1 Diese Norm verlangt ausdrücklich, dass bestimmte Standard-Bibliothek y-Funktionen sind conexpr (7.1.5). Eine Implementierung darf keine Standardbibliotheksfunktion als consExpr deklarieren, außer für solche, bei denen explizit erforderlich ist. Innerhalb jeder Kopfzeile, die nicht-definierende Deklarationen von constexpr Funktionen oder Konstruktoren bereitstellt, muss eine Implementierung entsprechende Definitionen bereitstellen.

Ohne die constexpr vor Ihrer LookupTable wird es in der Tat zur Laufzeit initialisiert werden. Eine Umgehung ist es, eine static Variable zu machen, so dass Sie es bei der Inbetriebnahme initialisieren können.

Wenn Sie constexpr mathematische Funktionen wollen, müssen Sie Ihre eigenen schreiben, oder alternativ einen Standard-Vorschlag schreiben, die die aktuelle <cmath> Bibliothek modifizieren constexpr zu sein.

Verwandte Themen