2012-04-19 54 views
1

我的意思是'中間'函數是:一個正常的函子,其中一個參數可以在調用時指定。問題是我有一個動畫時間線(基本上是特定幀的標量值),並且這個輸出需要通過管道傳入和傳出要設置動畫的對象中的getter/setter方法。以下是我試圖一個簡單的例子:C++試圖創建一個'Intermediate'函子

template < class ObjType, class Getter, class Setter, typename Scalar > 
class Sy_propertyBridge : public Sy_abstractPropertyBridge 
{ 
public: 
         Sy_propertyBridge(ObjType* object, Getter getter, 
              Setter setter) 
          : obj_(object), get_(getter), 
           set_(setter) {} 
    virtual   ~Sy_propertyBridge() {} 

    inline virtual float get() const 
         { 
          // Cannot handle default arguments. 
          Scalar tmp = (obj_->*get_)(); 
          return static_cast<float>(tmp); 
         } 
    inline virtual void set(float value) 
         { 
          Scalar tmp = static_cast<Scalar>(value); 
          (obj_->*set_)(tmp); 
         } 
private: 
    ObjType*   obj_; 
    Getter    get_; 
    Setter    set_; 
}; 

的時間表僅持有浮動,因此無論標量類型的對象使用它的getter/setter方法,必須強制轉換(我有一個浮動的偏特那消除演員)。 ObjType是動畫對象類型,GetterSetter是指向方法的指針,而Scalar是Getter和Setter類型並有望處理。

我認爲這樣可以,但編譯失敗,因爲一些getter/setter有其他的默認初始化參數。我不認爲這會是一個問題,因爲它們是默認的!但是當編譯器期望指向方法的指針比我提供的更多時,它失敗了。

然後我嘗試使用可變參數模板參數,以便默認值可以手動放入,但落在第一個障礙,因爲我不能將參數包存儲爲一個成員,作爲參數重複應用到指針-方法。我也一直在尋找std :: function和std :: bind,我希望能夠通過getter/setter方法的默認參數預設將std :: function存儲爲成員,並將相應的arg從調用之前的時間線。只有我找不到辦法...

有沒有人有任何建議來實現我的目標?或者,我的設計從根本上有缺陷,有一個更簡單的方法?

回答

1

std::function將是要走的路。將僅使用std::function<Scalar(const ObjType*)>作爲您的獲取者,std::function<void(ObjType*, Scalar)>作爲您的設置者(如果Scalar s可隱式轉換爲/從float s,我甚至會使用std::function<float(ObjType const*)>std::function<void(ObjType*, float)>或分別)。你可以初始化這些例如。與lambda函數:

Sy_propertyBridge(my_obj, 
    [](const MyObjType* o) -> float { return o->opacity; }, 
    [](const MyObjType* o, float f) { o->opacity=f; }) 

注意,有可能是這樣做的更優雅的方式(例如,有可能是隻有一個功能,可以既作爲一個getter和一個setter)。

把它更進一步,你可以

  • 擺脫obj_成員變量
  • 擺脫o參數對功能的

的lambda表達式將不得不記住他們將操作的對象。因此,上述構造函數調用將變爲

Sy_propertyBridge(
    []() -> float { return my_obj->opacity; }, 
    [](float f) { my_obj->opacity=f; }) 
+0

我一直在試圖找到一個藉口來使用lambda的!謝謝,我會放棄它,並讓你知道我如何繼續。 – cmannett85 2012-04-20 06:03:38

+0

美妙地工作,一個奇妙的解決方案。 – cmannett85 2012-04-21 07:53:32

0

根據我的理解,您試圖使用「get」和「set」方法,這些方法在您傳入的每個類中有所不同?如果是這樣,我認爲你應該試圖在你的「ObjType」對象上使用純粹的虛擬基類,然後在你傳入的類中實現它。在C#/ Java術語中,是一個接口。

基本上這樣的:

class IGetSetter 
{ 
    virtual float get() const = 0; 
    virtual void set(float) = 0;  
} 

class ObjType1 : public IGetSetter 
{ 
    virtual float get() const 
    { 
     // Implementation 
    } 

    virtual void set(float a) 
    { 
     // Implementation 
    } 
} 

class ObjType2 : public IGetSetter 
{ 
    virtual float get() const 
    { 
     // Implementation 
    } 

    virtual void set(float a) 
    { 
     // Implementation 
    } 
} 

然後你的類就變成了:

template < typename Scalar > 
class Sy_propertyBridge : public Sy_abstractPropertyBridge 
{ 
public: 
    Sy_propertyBridge(IGetSetter* object) 
     : obj_(object) {} 
    virtual ~Sy_propertyBridge() {} 

    inline virtual float get() const 
    { 
     Scalar tmp = obj_->get(); // Uses polymorphism to find the right method 
     return static_cast<float>(tmp); 
    } 
         } 
    inline virtual void set(float value) 
    { 
     Scalar tmp = static_cast<Scalar>(value); 
     obj_->set(tmp); // Uses polymorphism to find the right method 
    } 
private: 
    ObjType* obj_; 
}; 

但實際上,有可能完全砍掉你的Sy_propertyBridge類的簡單方法。只需存儲指向IGetSetter的指針數組,然後直接調用這些指針,只要它們按照您的要求操作即可。

+0

動畫對象可以具有任意數量的動畫屬性,因此單個get/set方法不夠。同樣在維護級別上,使用用戶指定的橋接對象將對象的動畫屬性與其時間線完全分離,並允許最終用戶通過斷開連接來禁用它們。但原則上,你沒有錯。 – cmannett85 2012-04-20 06:01:22