1

Visual Studio 6 では完全に機能するテンプレート クラスがありますが、最新バージョンでは機能しません。

template<double B, double C>
class MyClass
{
    double k(double x) const
    {
        x = fabs(x);
        if (x < 1.0)
            return ((2.0 - 1.5*B - C) * x*x*x) + ((-3.0 + 2.0*B + C) * x*x) + (1.0 - 0.33333333*B);
        if (x < 2.0)
            return ((-0.16666667*B - C) * x*x*x) + ((B + 5.0*C) * x*x) + ((-2.0*B - 8.0*C) * x) + (1.3333333*B + 4.0*C);
        return 0.0;
    }
};

error C2993: 'double' : illegal type for non-type template parameter 'B'

私はそれを理解しましたdouble、テンプレートパラメータとして定数を使用することは許可されていない標準であり、VC++ は最終的に準拠しています。しかし、代わりに何を使用すればよいでしょうか? 式は繰り返し評価され、真のボトルネックです。実行時ではなくコンパイル時に定数を計算したいと考えています。

4

2 に答える 2

1

問題は、テンプレート引数をプログラム全体のインスタンス化のセットに一致させることが正確な等価性に依存することです。これは、マシンの特定の浮動小数点値の表現に基づいて、プラットフォームごとに異なる場合があります。(また、コンパイラはターゲット マシンのコンパイル時のエミュレーションを提供する必要がないため、コンパイル時と実行時で異なる場合があります。)

double解決策は、比率、100 万などの固定量を超える分数、または整数の仮数と指数を使用した独自の浮動小数点スタイルなど、他の種類の明確な表現に置き換えることです。

C++11 では、関数評価を適用できますconstexpr。この場合、テンプレートが削除されます。

struct MyClass {
    constexpr MyClass( double b, double c )
        : b15( b * 1.5 ), b20( b * 2.0 ), b03( b * 0.33333333 ),
        /* etc */

    double b15, b20, b03, /* etc */

    double k( double x ) const {
        x = fabs(x);
        if (x < 1.0)
            return ((2.0 - b15 - C) * x*x*x) + ((-3.0 + b20 + C) * x*x) + (1.0 - b03);
        /* etc */
    }
};

これにより、定数部分式が事前計算され、単一の共通関数に対する実行時パラメーターが効果的に作成されます。ただし、パラメーター/メンバー オブジェクトへのアクセスによって速度が低下する可能性があります。

関数を常にインライン化できる場合、その代替手段はおそらく元のテンプレートと同様の結果をより少ない労力で生成します。

于 2013-11-14T06:00:07.627 に答える
0

constexpr 関数を使用する場合、return ステートメントは 1 つしか持てないため、?: 演算子を使用する最小限のコストで必要なすべてを実行する必要があります。

constexpr double k(double B, double C, double x) const
{
    x = fabs(x);
    return 
          (x < 1.0) ? 
               ((2.0 - 1.5*B - C) * x*x*x) + ((-3.0 + 2.0*B + C) * x*x) + (1.0 - 0.33333333*B)
        : (x < 2.0) ?
           ((-0.16666667*B - C) * x*x*x) + ((B + 5.0*C) * x*x) + ((-2.0*B - 8.0*C) * x)
           + 1.3333333*B + 4.0*C)
        : 0.0;
}

ただし、x はリテラル (コンパイル時に既知) である必要があります。

残念ながら、VSを使用しないことも必要です

http://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx

x が変数 (実行時に変更) であるか、VS を使用している場合:

constexpr上記のキーワードを削除するだけです。ほとんどの最適化は、コンパイル時に B と C が既知であるという事実から単純に行われる可能性があります - asm をチェックして確認してください。(アップグレードは厳密性を高めるだけでなく、最適化も改善する可能性があります)

于 2013-11-14T07:33:43.593 に答える