6

一部のデータに対してフィルタリングを実行したい場合、実行時にこのデータを生成することを回避しながら、これらのフィルターのサイズとデータ分散を変更する柔軟性を維持しながら、クリーンで再利用可能なコードを維持するにはどうすればよいでしょうか。テンプレートを使用して次のようなことができることを知っています。

template <int x> class Filter
{
  static const float f;
  static const Filter<x-1> next;
  inline float* begin(const Filter<x>& el){ return  &f;      }
  inline float* end(const Filter<x>& el)  { return (&f)+x+1; }
};
template <> class Filter<0>
{
  static const float f;
  inline float* begin(const Filter<0>& el){ return  &f;    }
  inline float* end(const Filter<0>& el)  { return (&f)+1; }
};

template <int x> const float Filter<x>::f = someDistribution(x);
template <>      const float Filter<0>::f = someDistribution(0);

これは確かに someDistribution(...) に従ってフィルター オブジェクトのインデックス x に従って私のフィルターでデータを生成します。しかし、私の使い方にはいくつかの欠点があります...

1)このデータはオブジェクトの構築時に生成されませんが、プログラムの開始時に一度生成されると言っているのは正しいと思います。-これは許容できますが、むしろフィルターがcomiletimeで計算され、その場で焼き付けられます(これはfloatデータでも可能ですか?)

2) 構造体の長さをトラバースするメンバー関数 (どこかで呼び出される!) がない限り、フィルターは「次の」メンバーをインスタンス化しません。

// inside template<int x> class Filter
inline void instantiate() const { next.instantiate(); };
// then inside template<> class Filter<0>
inline void instantiate() const { };

急落するインスタンス化関数を要求するのは間違っているに違いありません。これは、保守が容易な句に失敗します。

編集:ここで気にする理由は、nextメンバーがインスタンス化されていることを確認して、begin 関数と end 関数を使用して静的な「配列」を走査できるようにしたいからです。

まず、問題 2 を修正してインスタンス化関数を廃止するにはどうすればよいでしょうか。次に、問題 1 を修正して、このデータがコンパイル時に動的に生成されてバックインされるようにすることは可能ですか。

(注意: 同様の問題について、Python のプリコンパイル スクリプトを使用してフィルター データを含むソース ファイルを生成しましたが、ここではそれを使用したくありません。これは独自の魚のやかんです!)

4

2 に答える 2

2

使えないのでcontexpr・・・ ご質問について

  1. 次に大きい素数を探しているのでない限り、起動時に単純な計算が 1 回行われることに悩まされることはありません。測定してみると、初期化が 1 ミリ秒未満で完了していることがわかる可能性があります。

    とは言っても、起動時に計算された値は変数として動作します (asked使用されるたびにその値を使用する必要があります) が、コンパイル時の定数の値は常に既知です。したがって、前者は少し遅くなる可能性がありますが、おそらく意味はありません。

    不便を導入する前に、必ず最初に測定してください。

  2. 繰り返しますが、なぜあなたは気にしますか?Filtertype for specificがコードのどこにも使用されていない場合x、なぜその値がどこかにある必要があるのでしょうか?

    テンプレートの静的は、互いに依存している場合に問題があります-あなたの場合、そうではなく、それぞれfが自律的です。

そうは言っても、いじくり回すのに最適なツールはhttp://gcc.godbolt.org/です。入力するとアセンブリが表示されます。MS コンパイラはサポートしていませんが、コンパイラがどのように最適化するかについてかなりの推測ができます。

配布がマクロになるほど単純な場合、コンパイル時の定数になります。

#define someDistribution(x) x * x

template <int x> struct Filter
{
  static const float f;
};

template <int x> const float Filter<x>::f = someDistribution(x);

int main()
{
  return Filter<200>::f + Filter<100>::f;
}

アセンブリ (Clang):

main:                                   # @main
    movl    $50000, %eax            # imm = 0xC350
    ret

関数に変更someDistributionすると、インライン関数であっても、計算が必要になることがわかります。

編集:マクロを特定の値に「特化」するなど、マクロを使用して何でもできることを覚えておいてください。単純な配布は、プリプロセッサに適している必要があります。

于 2013-11-01T15:58:36.807 に答える
-1

可変個引数テンプレートを使用して、パズルの一部を取得できます。integer_sequence サポートが標準ライブラリに追加されると、seq / gen_seq ではなくそれを使用できます。

#include <array>
#include <iostream>

using namespace std;

template<size_t... Is> struct seq {};
template<size_t N, size_t... Is> struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
template <size_t... Is> struct gen_seq<0, Is...> : seq<Is...>{};

template<typename Func, size_t... Is>
const array<float, sizeof...(Is)>& make_coeffs(Func f, seq<Is...>) {
    static const auto coeffs = array<float, sizeof...(Is)>{ f(Is)... };
    return coeffs;
}

float square(float x) { return x * x; }

int main() {
    const auto coeffs = make_coeffs(square, gen_seq<10>{});
    for (float x : coeffs) {
        cout << x << " ";
    }
    cout << endl;
}

VS 2013にはないconstexprサポートが本当に必要ですが、これを起動時に初期化するのではなくコンパイル時に行うには。constexprバージョンは次のとおりです。

#include <array>
#include <iostream>

using namespace std;

template<size_t... Is> struct seq {};
template<size_t N, size_t... Is> struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
template <size_t... Is> struct gen_seq<0, Is...> : seq<Is...>{};

template<typename Func, size_t... Is>
constexpr array<float, sizeof...(Is)> make_coeffs(Func f, seq<Is...>) {
    return array<float, sizeof...(Is)>{ f(Is)... };
}

constexpr float square(float x) { return x * x; }

int main() {
    constexpr auto coeffs = make_coeffs(square, gen_seq<10>{});
    static_assert(coeffs[3] == 9, "");
    for (float x : coeffs) {
        cout << x << " ";
    }
    cout << endl;
}
于 2013-11-01T15:57:27.040 に答える