2012-04-18 260 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

相關問題