2016-04-08 11 views
4

で使用することはできません。私のコードは次の通りです:constexprの - 機能は、私は与えられた範囲内の数学関数のためにコンパイル時にルックアップテーブルを計算し、その後、実行時にテーブルから値を取得したい定数式

#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; 
} 

コードはgcc 5.1以上でコンパイルされ実行されますが、Clang 3.8ではコンパイルされずに実行されます。 クランのエラーメッセージは、次のとおりです。constexprの変数「テーブル」の定数式で使用することはできません定数式と非constexprの関数「EXP」で初期化する必要があります。

私はconstexprのを削除する場合:

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

、コードをコンパイルして、同様クラン上で実行されます。

私の質問は以下のとおりです。

  • 「定数式で使用することができない関数 『EXP』」エラーメッセージの意味は何ですか?回避策はありますか?
  • ことを意味している私は宣言するときにルックアップテーブル< 10000>テーブル(0.0、1.0)ん。 constexprなしでは、テーブルの事前計算は実行時に行われますか? オンラインのコンパイルツールを使用しているため、今すぐコードをベンチマークするオプションはありません。
  • 私は、コードを一般化し、数学関数をテンプレート化したいと思います。それはファンクターでうまく動作しますが、lambdaを使用することは可能ですか?

おかげ

答えて

6

これは<cmath>constexprせずに宣言されてexp()以来のgccの不適合延長のように見える:

17.6.5.6 constexprの機能とコンストラクタ[constexpr.functions]

1この規格は、明示的にその 一定の標準librarが必要ですy関数はconstexpr(7.1.5)です。 実装では、標準ライブラリ関数 の署名をconstexprとして宣言してはならず、明示的には が必要です。 constexprの関数やコンストラクタの任意の非規定 宣言実装は、対応する定義を提供しなければならない提供する任意のヘッダ内

LookupTableの前にconstexprがないと、実際には実行時に初期化されます。回避策は、起動時に初期化できるように、変数をstaticにすることです。

constexpr数学関数を使用する場合は、独自の関数を書くか、現在の<cmath>ライブラリがconstexprに変更されたという標準提案書を書く必要があります。

関連する問題