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]); }
};

问题 => 如果我想添加更多函数,我会复制粘贴我为 sin 函数所做的工作,以及每个函数(如 cos、sqrt、fabs 等)。我怎样才能避免这种复制粘贴?我尝试了一些东西,发现我的模板符仍然很低。不允许提升^^

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 回答