2016-10-28 3 views
1

私は、任意の数のパラメータを持つことができるユーザー提供の測定モデル関数を受け入れることができるカルマンフィルタークラスを実装しようとしています。カルマンフィルターに慣れていない場合は、基本的に、任意の数のパラメーターを持つ関数を受け取るテンプレートコンストラクターを持つ非テンプレートクラスがあります。次に、コンストラクタは渡された関数を関数ラッパー・メンバ・オブジェクトに割り当てます。それ自体は可変長テンプレート・クラスに基づいて作成されます。私が抱えている問題は、関数ラッパーオブジェクトを、カルマンフィルタークラスのメンバーとして、コンストラクターに渡す関数の特定の形式を知らなくても宣言する方法です。C++:非テンプレートクラスのメンバとして汎用関数ラッパークラス

これがあまり明確でない場合は、お詫び申し上げます。しかし、私は基本的にはthisの回答をthisにしています。ここで、auto add = make_action([] (int a, int b) { std::cout << a + b; }, 2, 3)というのは、非テンプレートクラスにメンバー変数として組み込みたい機能を表しています(割り当てはコンストラクタで行われます)。私はKFクラスはテンプレートクラスであった場合、問題はおそらく大幅に簡素化することができ確信しているが、私は本当にこれを行うにはしたくない

#include <iostream> 
#include <functional> 
#include <tuple> 

namespace Helper 
{ 
    template <std::size_t... Ts> 
    struct Index {}; 

    template <std::size_t N, std::size_t... Ts> 
    struct GenSeq : GenSeq<N-1, N-1, Ts...> {}; 

    template <std::size_t... Ts> 
    struct GenSeq<0, Ts...> : Index<Ts...> {}; 
} 

template <typename... ArgTps> 
class MeasModWrapper 
{ 
private: 
    std::function<void(ArgTps...)> MeasMod; 
    std::tuple<ArgTps...> MeasModArgs; 

public: 
    template <typename MsModFnc, typename... ArgTs> 
    MeasModWrapper(MsModFnc&& MsMod, ArgTs&&... args) 
     : MeasMod(std::forward<MsModFnc>(MsMod)), 
      MeasModArgs(std::make_tuple(std::forward<ArgTs>(args)...)) 
    {} 

    template <typename... ArgTs, std::size_t... Is> 
    void MsMod(std::tuple<ArgTs...>& tup, Helper::Index<Is...>) 
    { 
     MeasMod(std::get<Is>(tup)...); 
    } 

    template <typename... ArgTs> 
    void MsMod(std::tuple<ArgTs...>& tup) 
    { 
     MsMod(tup, Helper::GenSeq<sizeof...(ArgTs)>{}); 
    } 

    void CallMeasMod(void) 
    { 
     MsMod(MeasModArgs); 
    } 
}; 

template <typename MsModFnc, typename... ArgTs> 
MeasModWrapper<ArgTs...> BindMeasMod(MsModFnc&& MsMod, ArgTs&&... args) 
{ 
    return MeasModWrapper<ArgTs...>(std::forward<MsModFnc>(MsMod), std::forward<ArgTs>(args)...); 
} 

// The following is where my code differs from the solution provided by user 0x499602D2 (many thanks btw) 
class KF 
{ 
private: 
    auto measurementModel;    // <--- This doesn't work, and I expected that it wouldn't, but how can I get around this problem??? 

public: 
    template <typename MsFnc, typename... FncArgs> 
    KF(MsFnc&& msFnc, FncArgs&&... fncArgs) 
     : measurementModel(BindMeasMod(msFnc), std::forward<FncArgs>(fncArgs)...) 
    {} 

    void CallMeasMod(void) 
    { 
     measurementModel.CallMeasMod(); 
    } 
}; 

int main(void) 
{ 
    KF kf([](int x, int y){ std::cout << (x+y) << std::endl; }, 3, 4);   // Just a simple example function - in reality it could take any form and most likely wouldn't be a lambda function, but that's not particularly important at this stage. 
    kf.CallMeasMod(); 
    //auto measurementModel = BindMeasMod([] (int a, int b) { std::cout << a + b << std::endl; }, 3, 4);  // <-- This would work because it by-passess the KF class - BUT it is not what I want 
    //measurementModel.CallMeasMod(); 
    return 0; 
} 

は、ここに私のコードです。 Boostが私が望むものを達成するための何らかの方法を提供するかどうかはわかりませんが、可能であればSTLベースのソリューションを好むでしょう。このことについて私に何か助けてくれる人には、事前に多くの感謝をします。

私はvariadicテンプレートにはかなり新しく、正直言って私はまだ少し混乱しています(例えば、ヘルパーネームスペースのコードがどのように機能するかは100%は分かりません)。彼らは本当によく(ダミーのために)それらを説明する本やウェブサイトは、それはまた感謝します。

P.S. Ubuntu 14.04でg ++ 4.8.4を使用しています。


編集:

私はライブラリを構築しようとしていますことを言及するのを忘れてしまいました。 KFクラスには多くの追加機能がありますが、これはカルマンフィルタのすべての実装で標準です。各実装が異なるところは、測定モデル(とプロセスモデルですが、この例では測定モデルと同じ方法で処理されるため、これを含めていません)ですので、どのような種類の関数も処理できる必要があります任意の数のパラメータで呼び出すことができます。そして、その背後でKFクラス自体のさまざまなポイントでその関数を呼び出す一般的な方法を持っています(私がここに含まれているコードは、main関数で呼び出される測定モデル関数を示しています。ここでは呼び出されず、正確な形が不明なKFクラス内で使用されます)。ライブラリは、測定モデルとして使用する特定の機能を提供するエンジニアによって使用されるため、KFクラスの構築時に関数名とその引数を指定することになります。これはテンプレート化されていない通常の関数です。この例では単純なラムダ関数を使用しましたが、これは1行にきれいにフィットしていて、それは私が追っていた例でも使われていたからです。

+0

測定モデル関数のパラメータの種類は何ですか?彼らはテンプレート型ですか?それらはすべて同じタイプですか? – Sergey

+0

あなたのコンストラクタは、N個のパラメータとそれに付随するN個の引数をとる関数をとります。なぜ、あなたはすぐにそれらの引数でそれを呼び出し、(単数の)戻り値を格納しないのですか?あなたは、その呼び出しを遅らせるだけの多くのトラブルに行く。 –

答えて

0

'LLがあなたを行うが、これはあなたの例の作品を作ることは良い何明確ではない:

#include <iostream> 
#include <functional> 

class KF 
{ 
private: 
    std::function<void()> measurementModel; 

public: 
    template <typename MsFnc, typename... FncArgs> 
    KF(MsFnc&& msFnc, FncArgs&&... fncArgs) 
     : measurementModel([=]() { return msFnc(fncArgs...); }) 
    {} 

    void CallMeasMod(void) 
    { 
     measurementModel(); 
    } 
}; 

int main(void) 
{ 
    KF kf([](int x, int y){ std::cout << (x+y) << std::endl; }, 3, 4); 
    kf.CallMeasMod(); 
    return 0; 
} 

Demo

+0

不思議なことに、これはClang(デモで使われている)でうまく動作しますが、g ++でコンパイルされません。 – SecretAardvark

+0

[Does too](http://rextester.com/IVIF94438) –

+0

'-std = C++ 11'または' -std = C++ 1y'のg ++​​ 4.8.4ではありません。私はC++ 14が必要だと思うが、4.8.4のC++ 1yはC++ 14の実験的なサポートのみを提供する。 – SecretAardvark

関連する問題