2016-10-14 5 views
0

私はMyClassのこれら2つのメンバ関数を持っていた:このコードをランタイムに影響を与えずに分解できますか?

Result MyClass::func1(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam1& extraParam1) 
{ 
    Result result; 
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3 
    doSomething(1, commonParam1, commonParam2, extraParam1); 
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3 
    return result; 
} 

Result MyClass::func2(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam2& extraParam2, const ExtraParam3& extraParam3) 
{ 
    Result result; 
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3 
    doSomething(1, commonParam1, commonParam2, extraParam2, extraParam3); 
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3 
    return result; 
} 

私は正確に両方の機能のために同じですプロローグ/エピローグコード(の重複を避けるために、これを因数分解する必要が修正MyClassの属性で、プロローグはで使用される変数を作成しますエピローグ...そのようなもの)。唯一の違いは、別のバージョンのMyClass::doSomethingが(異なるパラメータを使用して)呼び出されることです。 doSomethingは異なるパラメータセットと呼ばれているように、私は、テンプレートを使用してヘルパークラスを導入する因数分解のためにこのアプローチを使用:

class helper1 
{ 
public: 
    helper1(const ExtraParam1& extraParam1) : extraParam1(extraParam1) {} 
    inline bool compute(MyClass& parent, const CommonParam& commonParam1, const CommonParam& commonParam2) const 
    { 
     return parent.doSomething(1, commonParam1, commonParam2, extraParam1); 
    } 

private: 
    const ExtraParam1& extraParam1; 
}; 

class helper2 
{ 
public: 
    helper2(const ExtraParam2& extraParam2, const ExtraParam3& extraParam3) : extraParam2(extraParam2), extraParam3(extraParam3) {} 
    inline bool compute(MyClass& parent, const CommonParam& commonParam1, const CommonParam& commonParam2) const 
    { 
     return parent.doSomething(1, commonParam1, commonParam2, extraParam2, extraParam3); 
    } 

private: 
    const ExtraParam2& extraParam2; 
    const ExtraParam3& extraParam3; 
}; 

template<typename Helper> 
inline Result funcT(MyClass& parent, 
        const CommonParam& commonParam1, 
        const CommonParam& commonParam2, 
        const CommonParam& commonParam3, 
        const Helper& helper) 
{ 
    // this function is a friend of MyClass, so prolog/epilog can use any private class attribute 

    Result result; 
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3 
    helper.compute(parent, commonParam1, commonParam2); 
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3 
    return result; 
} 

Result MyClass::func1(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam1& extraParam1) 
{ 
    return funcT(*this, commonParam1, commonParam2, commonParam3, helper1(*this, extraParam1)); 
} 

Result MyClass::func2(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam2& extraParam2, const ExtraParam3& extraParam3) 
{ 
    return funcT(*this, commonParam1, commonParam2, commonParam3, helper2(*this, extraParam2, extraParam3)); 
} 

これらの機能は、当社のアルゴリズムによって倍の十億と呼ばれていますので、リファクタリングが最低を持っている必要がありますランタイムインパクト。

computeinlineです。実行時の影響を最小限に抑えるために、すべてが参照渡しであり、仮想テーブルではなくテンプレートを使用しました。しかし、私は(少なくとも、我々はhelper1helper2オブジェクトを作成します)これは、実行時に影響を与えていると思います。

私のリファクタリングは、コンパイラは削除しないことを、ランタイム影響がありますか? そうならば、誰かが低く、ランタイム影響がリファクタリングを提案しているだろうか?

答えて

2

私のリファクタリングは、コンパイラが削除されませんランタイムインパクトを持っていますか?はいの場合、誰かが実行時間の影響が少ないリファクタリングを提案できますか?

のオーバーヘッドが導入されていないことを確認する唯一の方法は、です。リファクタリング前/後にあなたのコードをプロファイリングし、は、生成されたアセンブリをご確認ください。


補足として、コードをリファクタリングしてコンパイラがインライン化するのはやや簡単な方法です。代わりに、追加のパラメータへの参照を格納する、それらは一般的な呼び出し可能オブジェクトに完全に-転送されます。

template <typename TF, typename... TExtraParams> 
Result MyClass::generic_func(const TF& doSomething, const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const TExtraParams&&... extraParams) 
{ 
    Result result; 
    // prolog code, common to all, using commonParam1, commonParam2, commonParam3 
    doSomething(1, commonParam1, commonParam2, std::forward<TExtraParams>(extraParams)...); 
    // epilog code, common to all, using commonParam1, commonParam2, commonParam3 
    return result; 
} 

あなたの現在の設計では、以下のように、それは使用することができます。

generic_func([](
    const CommonParam& a, const CommonParam& b, const CommonParam& c, 
    const ExtraParam& extra0 
) 
{ 
    // ... will be called between prolog and epilog 
}, my_a, my_b, my_c, extra0); 
関連する問題