3

個人的な悟りの練習として、式テンプレートを使用してベクトル演算を実装します。ベクトル式のすべての要素に同じ単項関数を適用するいくつかの操作を実装したいと考えています。これまでのところ、私はこれを行います。

私の基本ベクトル式テンプレートは次のように実装されています

template <typename E>
class VectorExpr {
public:
  int size() const { return static_cast<E const&>(*this).size(); }

  float operator[](int i) const { return static_cast<E const&>(*this)[i]; }

  operator E& () { return static_cast<E&>(*this); }

  operator E const& () const { return static_cast<const E&>(*this); }
}; // class VectorExpr

次に、ベクトルであるはずのオブジェクトは次のようになります

class Vector2 : public VectorExpr<Vector2> {
public:
    inline size_t size() const { return 2; }

    template <typename E>
    inline Vector2(VectorExpr<E> const& inExpr) {
    E const& u = inExpr;
    for(int i = 0; i < size(); ++i)
        mTuple[i] = u[i];
   }

private:
   float mTuple[2];
};

式のすべての要素に std::sin を適用したいとしましょう

template <typename E>
class VectorSin : public VectorExpr<VectorSin<E> > {
    E const& mV;

public:
    VectorSin(VectorExpr<E> const& inV) : mV(inV) {}

    int size() const { return mV.size(); }

    float operator [] (int i) const { return std::sin(mV[i]); }
};

質問 => さらに関数を追加したい場合は、すべての単一関数 (cos、sqrt、fabs など) に対して、sin 関数に対して行うことをコピーして貼り付けます。この種のコピペを避けるにはどうすればよいですか? 私はいろいろ試してみましたが、まだ template-fu が少ないことがわかりました。ブースト禁止です^^

4

2 に答える 2

5
template <typename F, typename E>
class VectorFunc : public VectorExpr<VectorFunc<F, E> > {
    E const& mV;

public:
    VectorSin(VectorExpr<E> const& inV) : mV(inV) {}

    int size() const { return mV.size(); }

    float operator [] (int i) const { return f(mV[i]); }

    // this assumes the Functor f is default constructible, this is
    // already not true for &std::sin. Adding the constructor that
    // takes f, is left as an exercise ;)
    F f;
};
于 2012-04-18T16:17:04.650 に答える
2

pmrによる回答に加えて、標準<cmath>関数はファンクターではないため、それらを直接使用してクラスの固有の特殊化を指定することはできませんでした。つまり、std::sin と std: :cos (私が収集したのは、あなたが目指しているものですか? 誤解していた場合は訂正してください)。

関数ポインタを個別の型にマップするためにラッパーを作成できます。

#include <iostream>

template< void (*FuncPtr)() > struct Func2Type
{
    void operator() () { FuncPtr(); }
};

void Hello() { std::cout << "Hello" << std::endl; }
void World() { std::cout << "world" << std::endl; }

int main()
{
    Func2Type<Hello> test1;
    Func2Type<World> test2;
    test1(); 
    test2();
}

そうすれば、通常のファンクター クラスと同じ方法で、それらをテンプレート引数として使用できます。

于 2012-04-18T16:31:01.127 に答える