2013-12-11 61 views
2

我懷疑我可能在這裏指責OT,請原諒我。 - 只是在案例中 -模板功能與一些非常見的部分

我有一個小問題,我覺得很多哲學比真正的編程問題,但仍然讓我感到不舒服,我希望一些專家的意見。

假設我們正在使用的所有它允許操縱可能的類型T表現幾乎相同的方式模板功能:

//Perform the rendering 
template< typename T > 
long drawing_facility::render(typename object_cnt<T>::type& elements, draw_type type) 
{ 
    .... 
    //Any computation needed? 
    if(!obj->render_init_done.test_and_set(std::memory_order::memory_order_acquire)) 
    { 
     .... 
    } 
    .... 
} 

在這段代碼我跳過了所有的東西,我認爲是除了不必要的一個if聲明。 if檢查被處理的對象中的原子標記,以確定是否需要特殊的「計算」,如果需要在繼續執行「通用」任務之前完成某些操作。

我的問題是render是一個模板,應該以同樣的方式表現爲所有可能和允許T,但萬一render_init_done設置爲false不同的東西需要做,在if代碼對於所有的T s都不常見。

我通過向模板添加第二個參數非常快速地解決了這個問題,該參數告訴代碼模板正在處理哪種類型,並在此基礎上在if中執行不同的操作。

我真的懷疑這不是解決問題的最優雅的方法,你對如何管理這個功能有不同的意見嗎?

我想避免巨大的重複也太多函數調用,這樣的事情應該做的工作:

//Perform the rendering 
template< typename T > 
long drawing_facility::render(typename object_cnt<T>::type& elements, draw_type type) 
{ 
    render_part_a<T>(elements); 
    //Any computation needed? 
    if(!obj->render_init_done.test_and_set(std::memory_order::memory_order_acquire)) 
    { 
     ... 
    } 
    render_part_b<T>(elements); 
} 

//Perform the rendering, part a 
template< typename T > 
long drawing_facility::render_part_a(typename object_cnt<T>::type& elements) 
{ 
    ... 
} 

//Perform the rendering, part b 
template< typename T > 
long drawing_facility::render_part_b(typename object_cnt<T>::type& elements) 
{ 
    ... 
} 

但是,這是更好的辦法來解決這個問題?現在,調用render意味着另外兩個函數調用,這應該不是什麼大事,直到我可以保證render_part_arender_part_b的獨立性,實際上我可以,但只能用一些骯髒的黑客和微妙的參數傳遞 - 解決方法。

感謝

小更新:後@Nim的建議,我認爲這個問題可以使用一些重載函數來解決,請看一看這個非常簡單的例子中,我刪除了從渲染 - 不是第二個參數需要了 - :

typedef enum draw_type { 
    draw_text = 0, 
    draw_vertex = 1 
} draw_type; 

class drawable 
{ 
public: 
    virtual void foo() = 0; 
}; 

class text : drawable 
{ 
public: 
    void foo() {}; 
}; 

class vertex : drawable 
{ 
public: 
    void foo(){}; 
}; 

template< typename T > 
class drawable_object 
{ }; 

template< typename T > 
struct object_cnt 
{ 
    typedef std::vector< std::shared_ptr< drawable_object<T> > > type; 
}; 

class drawing_facility 
{ 
    void special(drawable_object<text>* obj) 
    { 
     std::cout<<"text\n"; 
    } 
    void special(drawable_object<vertex>* obj) 
    { 
     std::cout<<"vertex\n"; 
    } 
    public: 
     template< typename T > 
     long render(typename object_cnt<T>::type& elements) 
     { 
      //... 
      for(auto obj : elements) 
      { 
       //... 
       //the 'if' statement should be here. 
       special(obj.get()); 
       //... 
      } 
     //... 
     } 
}; 

int main() 
{ 
    typename object_cnt<text>::type a; 
    a.push_back(shared_ptr< drawable_object<text> >()); 
    typename object_cnt<vertex>::type b; 
    b.push_back(shared_ptr< drawable_object<vertex> >()); 
    drawing_facility draw; 
    draw.render<text>(a); 
    draw.render<vertex>(b); 
} 

希望代碼是足夠清晰。

+0

我不太確定我理解你的問題。你談論那個'if'以及代碼*在*中對於某些類型必須是不同的;但您的解決方案不會顯示該部分的任何變化。 – dyp

+0

也許我刪除了太多的代碼,在* if *語句中代碼檢查* type *的值並執行正確的操作。 – fjanisze

+0

@fjanisze:如果您發現有用的答案,請考慮投票。 – NeonGlow

回答

1

你已經通過,並不能意義,我的第二個策略...

我會做使用原始的方法,但是對於專業的計算,重載函數爲每個T ,例如..

struct A{}; struct B{}; struct C{}; 

void compute(A& obj) 
{ 
    // code for A 
} 

void compute(B& obj) 
{ 
    // code for B 
} 

void compute(C& obj) 
{ 
    // code for C 
} 

template <typename T> 
void render(T& obj) 
{ 
    .. // common stuff 

    if (!obj.computed()) 
    { 
    // now call overloaded function 
    compute(obj); 
    } 

    .. // common stuff 
} 
+0

這是一個好主意,我做了一個很好的小PoC,我會跟進一個小代碼的例子。 – fjanisze

0

如果您在代碼中使用內聯模板專業化功能而不是if,會更好嗎?這應該沒有問題的演出