2012-04-19 22 views
1

「中間」ファンクタとは、コール時に引数の1つを指定できる通常のファンクタです。問題はアニメーションタイムライン(本質的には特定のフレームでスカラー値)があり、その出力がアニメーション対象のオブジェクト内のゲッター/セッターメソッドとの間でパイプされる必要があることです。ここに私がしようとしていたかの簡単な例です:C++ '中級'ファンクタを作成しようとしています

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はゲッターとセッターのタイプで、対処が予定されています。

これはうまくいくと思いましたが、ゲッター/セッターの中にはデフォルトで初期化された他の引数がいくつかあるため、コンパイルに失敗しました。私はこれが問題になるとは思わなかった、なぜなら彼らはデフォルトだからだ!しかし、コンパイラが、私が提供していたよりもポインタへのメソッドの引数が多くなると予想したとき、それは失敗しました。

私はvariadicのテンプレートargsを使用してみましたので、デフォルト値を手動で入力することができましたが、パラメータパックをメンバとして格納することができないため、最初のハードルに落ちました。 - 方法。私はstd :: functionとstd :: bindも見てきましたが、getter/setterメソッドのデフォルトのargsプリセットを持つメンバとしてstd :: functionを格納できることを期待していました。呼び出し直前のタイムライン。私はそれを行う方法を見つけることができません...

私が目指していることを達成するための提案はありますか?または、私のデザインに根本的に欠陥があり、より簡単なアプローチがありますか?

答えて

1

std::functionです。ゲッターとしてstd::function<Scalar(const ObjType*)>を使用します(Scalarが暗黙的にfloatに変換可能な場合は、std::function<float(ObjType const*)>std::function<void(ObjType*, float)>を使用することもできます)。これらを初期化することができます。 (例えばゲッターとセッターとしての両方に仕えることができる唯一の機能がある可能性があります。)これを行うにはよりエレガントな方法があるかもしれません

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

。なお:ラムダ関数を持ちます。

さらにそれを取ると、あなたはラムダその後、覚えなければならないであろう機能にoパラメータ

を取り除くobj_メンバ変数

    • 取り除くことができ彼らが操作するオブジェクト。したがって、上記のコンストラクタコールはアニメーションオブジェクトがアニメーションプロパティの任意の量を有することができる

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

    私はラムダを使う言い訳を見つけようとしています!ありがとう、私はそれを行って、私はどのように乗っているかを教えてあげるよ。 – cmannett85

    +0

    美しい作品です。素晴らしいソリューションです。 – cmannett85

    0

    私が理解しているところでは、ここで渡すクラスごとに異なる "取得"メソッドと "セット"メソッドを使用しようとしていますか?もしそうなら、あなたは "ObjType"オブジェクトで純粋に仮想の基底クラスを使って、あなたが渡しているあなたのクラスに実装しようとするべきだと思います。

    基本的には、この:

    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クラスをaxingの簡単な方法は、おそらくあります:

    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 
        } 
    } 
    

    次に、あなたのクラスになります。ちょうどIGetSetterへのポインタの配列を格納し、それらがあなたが望むことをする場合は直接それらを呼び出す。

    +0

    なるので、単一のget/setメソッドが不十分です。また、メンテナンスレベルでは、ユーザー指定のブリッジオブジェクトを使用すると、タイムラインからオブジェクトのアニメーション可能なプロパティが完全に切り離され、エンドユーザーは接続を切断してオブジェクトを無効にできます。しかし原則として、間違っているわけではありません。 – cmannett85

    関連する問題