2016-05-02 46 views
3

私は次のような状況に苦しんでいます。関数はテンプレート引数で呼び出します

#include "systemc.h" 

template<int maxval> 
class Foo { 
    /* Error: calls to constructors and functions cannot be part of a constant expression */ 
    sc_uint<int(log2(double(maxval)))> a; 
    ... 
}; 

int main() { 

    Foo<10> foo; 
    ... 
    return 0; 
} 

上記のように、テンプレートクラス 'Foo'にはテンプレートパラメータ 'maxval'があります。 'Foo'はまた、テンプレートパラメータ 'maxval'をインスタンス化のためのテンプレート引数に 'log2'関数とともに使用するテンプレート化されたクラスをメンバとして保持します。しかしながら、図示されたコードは、例えば、関数呼び出しを定数式の一部にすることはできません。 評価する可能性はありますか。 log2(maxval)をコンパイル時に使用し、その結果を 'Foo'内のテンプレート引数に使用するのか?

ありがとうございました。 (私はGCC 4.1.2を使用しています)

答えて

8

テンプレートはコンパイル時の値を期待しています。これが機能するには、log2関数がconstexprである必要があります(そうではありません)。

独自のconstexpr機能を定義する必要があります。ベース2の対数関数の場合は、あなたが(浮動小数点部分をカットオフ)整数が必要な場合は、それが動作することができます:

constexpr int log2(int number, int acc = 0) { 
    return number <= 1 ? acc : log2(number/2, acc + 1); 
} 

編集:

私はその質問に気付きませんでしたconstexprをサポートしていないGCC 4.1を求めました。そのオプションが利用可能な場合にアップグレードを試みるべきですが、@ Florianの答えで提案されているように、テンプレートベースのソリューションに進むこともできます。

編集2:あなたがここにブースト、に依存したくない場合は

はあなたが使用することができ、簡単なテンプレートベースの実装です:

template<int V> 
struct log2 { 
    static int const value = 1 + log2<V/2>::value; 
}; 

template<> 
struct log2<0> {}; 

template<> 
struct log2<1> { 
    static int const value = 0; 
}; 

次にあなたが使用したいですとなり、3になります。

さらに別の編集:

constexpr実装は上記の間違いです0と負の数、のため0を返します。対数は(私はフォーマットするためのいくつかの改行を追加して、それは少し読めなくなってきたので)ゼロか(実際のドメインの)負の値のために定義されていないので、関数はエラーをスローするように調整することができます。

constexpr int log2(int number, int acc = 0) { 
    return number <= 0 
     ? throw std::logic_error{"Logarithm of zero or negative number not allowed."} 
     : number == 1 
      ? acc 
      : log2(number/2, acc + 1); 
} 
+1

GCC 4.1は、constexprのサポートより古いです。 –

+0

良い点、申し訳ありませんが、それに気付かなかった。コンパイラを更新する必要があります(オプションがある場合は、4.1が非常に古く、多くの新機能をサポートしていないので間違いなく実行する必要があります)、@ Florianのソリューションを使用してください。それを反映するように答えを更新します。 –

+0

@ Stjepan:あなたの提案に感謝します!私はテンプレートベースの解決策をとらなければならないと思います。なぜなら、 'constexpr'はGCC5.2.0でも私のために動かないからです。 – chessat2002

関連する問題