2012-01-14 7 views
4

基本的な考え方は、すべて同じことをするクラスの「ファミリ」がありますが、やや異なる方法です。この「ファミリ」は「高性能」ループで使用されるため、速度は本質的です。さらに、特定のファミリはコンフィグレーションファイルで指定されています。より効率的なC++の構造化/パターン化方法がありますか?

ここでの主な機能には驚異的なコードの繰り返しがあります。これを構造化するより良い方法があるので、HP<objx> testtest.loop(bobloblaw)を3回書く必要はありませんか?

class obj1 { 
public: 
    double f(double x) const { return 1.; } 
}; 

class obj2 { 
public: 
    double f(double x) const { return x; } 
}; 

class obj3 { 
public: 
    double f(double x) const { return x*x; } 
}; 

template <class O> 
class HP { 
private: 
    O obj; 

public: 

    double loop(const vector<double>& x) { 
     double s = 0.; 
     for (auto i : x) s += obj.f(i); 

    return s; 
    } 
}; 

int main() { 
    string config = "bob"; 
    double result = 0; 
    vector<double> bobloblaw; 

    /* Read configuration file to determine which object to use. */ 
    if (config == "obj1") { 
     HP<obj1> test; 
     result = test.loop(bobloblaw); 
    } else if (config == "obj2") { 
     HP<obj2> test; 
     result = test.loop(bobloblaw); 
    } else if (config == "obj3") { 
     HP<obj3> test; 
     result = test.loop(bobloblaw); 
    } 

    return result; 
} 
+0

+1ぼろぼろの場合 – JeremyFromEarth

+0

+1の場合、逮捕された開発参照。 –

答えて

4

次はテストされていないが、動作するはずです:

class obj1 
{ 
public: 
    double f(double x) const { return 1.; } 
}; 

class obj2 
{ 
public: 
    double f(double x) const { return x; } 
}; 

class obj3 
{ 
public: 
    double f(double x) const { return x*x; } 
}; 

class HPbase 
{ 
public: 
    virtual double loop(const vector<double>&) = 0; 
}; 

template <class O> class HP: 
    public HPbase 
{ 
public: 
    double loop(const vector<double>& x) 
    { 
    double s = 0.; 
    for (auto i : x) 
     s += obj.f(i); 
    return s; 
    } 
private: 
    O obj; 
}; 

std::unordered_map<std::string, std::unique_ptr<HPbase>> decode{ 
    {"obj1"}, new HP<obj1>()}, 
    {"obj2"}, new HP<obj2>()}, 
    {"obj3"}, new HP<obj3>()} }; 

int main() 
{ 
    string config = "bob"; 
    double result = 0; 
    vector<double> bobloblaw; 

    /* Read configuration file to determine which object to use. */ 
    result = decode[config].loop(bobloblaw); 
} 

注添加だけがHP<>の基底クラスと、コードのif/elseロジックを置き換えるマップであること。

+0

ありがとうございます - これは完璧で、正確に私が得ることを望んでいた答えのタイプです。 – notrick

+0

なぜunordered_mapですか?ここでstd :: mapを使用する方が良いか速いのですか? –

+0

@DavidFeurle:このケースでは、1つのルックアップがあるため、おそらく問題ありません。しかし、一般的に 'std :: map'ルックアップはO(log n)であり、' std :: unordered_map'ルックアップはO(1)です。したがって、十分なエントリがある場合、 'unordered_map'ルックアップはより高速になります。少数のエントリーでは、どちらが速いのかはわかりません(実装にも依存するかもしれませんが)とにかくボトルネックになることはまずありません。しかし、エントリが少ない場合、 'std :: map'はおそらくメモリ効率が良いでしょう。 – celtschk

3

あなたが同じ親/ wのこれらの3つのクラスのすべてのことのサブクラスを持っていませんでした(実際には、このコードの塊が... 2よりも多くの行ですか)? mainは依然として正しいサブクラスを使用してテストに割り当てる必要がありますが、テスト自体は共通のスーパークラスであると宣言されます。

ここでの欠点は、バージョンが使用されるtest.loopのコードをコンパイラがいつ作成するかをコンパイラが知りません(実行時に決定する必要があるため)。

これを回避する別の方法として、共通コードをマクロとして書き込むことができます。これは、一度しか書き込まれず、3つの異なるコピーに展開されます。それぞれのコンパイラは、テストが使用されています。デバッグを邪魔にすることはできますが、パフォーマンスに重点を置いている場合は、ソースの冗長性を減らす(とオブジェクトにはあまりない)、それは良いトレードオフになるかもしれません。

+0

この決定はユーザーの入力に依存するため、実行時には常に行われます。 –

+0

USEDを取得するのは実行時に決定されます。コンパイル時に各バージョンに対して実行されるコードが生成されるため、コンパイラは各タイプのサブクラスごとに異なるバージョンのコードがあれば、各バージョンをよりよく最適化することができます。 –

+0

マクロの使用を提案していますが、その危険性にもかかわらず有効な用途があります。 –

関連する問題