2013-10-01 5 views
5

私はジェネリックアルゴリズムを構築しようとしています。これまでのところ、以下の例のように、私は、クラス階層とポインタを使用して、これを達成している次のように動的多型ではなく静的なC++

struct Base{ 
    virtual double fn(double x){return 0;} 
}; 

class Derived : public Base{ 
    double A; 
public: 
    Derived(double a) : A(a) {} 
    double fn(double x) { return A*x;} 
}; 

//Some other implementations 

class algo{ 
    double T; 
    std::unique_ptr<Base> b_ptr; 
public: 
    algo(double t, std::unique_ptr<Base>& _ptr); //move constructor... 
    //Some constructors 
    double method(double x){ return T*b_ptr->fn(x);} 

}; 

このセットアップ後、実装されています。

int main(){ 
    std::unique_ptr<Derived> ptr(new Derived(5.4)); 
    algo(3.2,ptr); 
    method(2.4); 

    return 0; 
} 

これはもちろん非常に単純な例であり、しかし、それは私の質問に役立ちます。私が理解しているところでは、このように派生クラスを使用すると、メソッドがコンパイル時ではなく実行時に選択されます。私は自分のアルゴリズムから動的な振る舞いを必要としないので、すべてがコンパイル時に決定されます。これは効率の無駄です。コンパイル時に静的多型を実行する方法はありますか?

私が理解するところでは、テンプレートを使用して静的多型を得ることが可能です。しかし、私はプリミティブではないタイプのインプリメンテーションテンプレートを見つけることができませんでした。上記の例のように、デフォルト以外のコンストラクタを持つ派生クラスが必要ですが、これは可能ではないようです...誰にどのようにして解決策を提示できますか?

+0

不要についてのあなたの観察動的な振る舞いは賢明です:実行時に必要な実際の型を決定する必要がある場合は、多態的なクラス階層しか持たないようにしてください。良い例は、ネットワークプロトコルからのメッセージの解析、またはイベントループのイベントの処理です。そうでなければ、あなたが実際に必要とするタイプを知っていれば、仮想関数多形性は正しいツールではありません。 –

+0

'テンプレートを使って静的多型を得ることしかできません.'多態性は、現在のオブジェクト型の正しい関数の基底を呼び出すことです。だから関数のオーバーロードは静的多型であるとも言いたい。 – ZijingWu

答えて

3

あなたの基底クラスと派生ので、我々は最も可能性の高い、完全に多型を廃止し、アルゴに関数を渡すことができ 、唯一のメンバ関数を持つ関数を表しているように見える:

#include <iostream> 
#include <utility> 

template <class Function> 
class algo 
{ 
    double t; 
    Function fn; 

public: 
    algo(double t, const Function& fn) 
     : t{t}, fn{fn} 
    { } 
    double method(double x){ return t * fn(x);} 

}; 

template <class Function> 
algo<Function> make_algo(double t, Function&& fn) 
{ 
    return algo<Function>(t, std::forward<Function>(fn)); 
} 

int main() 
{ 
    const double someValue = 123; 
    const double anotherValue = 987; 

    auto algo = make_algo(anotherValue, [someValue](double otherValue) { 
     return someValue * otherValue; 
    }); 

    std::cout << std::fixed << algo.method(321) << std::endl; 
} 
+0

それをさらに一般化して、テンプレートパラメータの倍増もすることができます。 – goji

+0

これは非常に興味深い応答です、ありがとうございました! 1つの関数クラスの例は単純なものでした。通常、派生クラスは複数の関数を持ち、関数は非常に複雑です。関数の渡し方はあまりにも近すぎるでしょう!関数を事前に定義して渡すことができますか?私はstd ::関数ラッパーを発見したばかりですが、これは上記のメソッドと似ていますか、それとも動的な多態性を使用していますか? – Plamen

+0

関数をテンプレートとして渡す代わりに 'std :: function'を使用すると、コードが遅くなる可能性があります。あなたのもう一つの選択肢は、ポリシークラスを使用することです。これは、アルゴリズムメソッドの静的バインディングを使用して、より多くの経路を必要としている可能性があります。 – goji

関連する問題