I am trying to implement a Kalman filter class that can accept a user provided measurement model function, which can have any number of parameters. If your not familiar with Kalman filters it doesn't matter, basically I have a non-template class that has a templated constructor that receives a function with any number of parameters of any type. The constructor then assigns the passed function to a function wrapper member object, which itself is constructed based on variadic template classes. The problem I am having is how do I declare the function wrapper object as a member of my Kalman filter class without knowing the specific form of the function that will be passed to the constructor?
I apologise if this is not very clear. However, I have basically been following this answer to this question, where the line auto add = make_action([] (int a, int b) { std::cout << a + b; }, 2, 3)
represents the functionality that I want to incorporate into my non-template class as a member variable (with the assignment taking place in the constructor).
Here is my code:
#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;
}
I'm sure the problem could probably be greatly simplified if the KF class was a template class, but I really don't want to have to do this. I don't know if Boost would provide some way of achieving what I want but I would prefer a STL based solution if possible. Many thanks in advance for anyone who can offer me any help on this.
I'm fairly new to variadic templates, and to be honest I still find them a bit confusing (e.g. I'm not 100% sure how the code in the Helper namespace works) so if anyone can also recommend a good book or website that explains them really well (for dummies) then that would also be appreciated.
P.S. I'm using g++ 4.8.4 on Ubuntu 14.04, if that matters.
Aucun commentaire:
Enregistrer un commentaire