2012-04-18 257 views
2

作为我个人启发的练习,我使用表达式模板实现了向量数学。我想实现一些将所有元素应用到一个向量表达式的相同一元函数的操作。到目前为止,我这样做。传递一个仿函数作为C++模板参数

我的基本矢量表达式模板实现这样

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对象::罪到表达式的所有元素

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

Question =>如果我想添加更多函数,复制粘贴我为sin函数执行的操作,对于每个函数(如cos,sqrt,fabs等)。我怎样才能避免这种复制粘贴?我尝试了一些东西,发现我的模板功能还很低。无升压允许^^

+1

既然你学习,你应该尝试一起C++ 11的lambda表达式使用的std :: for_each的() ([示例](http://en.wikipedia.org/wiki/Anonymous_function#C.2B.2B)) – CAFxX 2012-04-18 16:15:37

+0

感谢您的建议,我会的!其实,我应该可以在没有C++ 11的情况下完成。我经常在群集上运行数字代码,其中编译器并不完全流血。 – Monkey 2012-04-19 00:28:58

回答

4
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; 
}; 
+0

我尝试了一些与此相近的东西。它因为你提到的std :: sin问题而失败。所以我的问题是关于如何使用像std :: sin这样的函数来实现它。 GCC错误信息在这里不是很有帮助... – Monkey 2012-04-19 00:53:23

+0

@Monkey我省略了这部分,因为我不知道如何将它添加到您的宏程序中:您需要添加一个构造函数,该函数使用函子“F”并初始化该成员(可能为它提供了一个默认参数,所以它仍然可以与DefaultConstructible函子无缝地工作)。 – pmr 2012-04-19 09:12:45

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

这样,你可以用它们作为模板参数以同样的方式作为一个正常的函数子类

+0

也被称为不推荐使用的'std :: pointer_to_unary/binary_function'我们应该让它们休息片段。 (他们可能已经休息的时间比他们已经过时的时间还要长,无用的混蛋;) – pmr 2012-04-18 16:38:35

相关问题