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.
Edit:
I forgot to mention that I am attempting to build a library. The KF class will have a lot of additional functionality, but this is standard across all implementations of a Kalman filter. Where each implementation differs is in the measurement model (and process model, but I haven't included that in this example as it will be handled in the same way as the measurement model) so I need to be able to handle any kind of function with any number of parameters and then have a common way of calling that function at various points within the KF class itself behind the scenes (the code I have included here shows the measurement model function being called in the main function, but in reality it will not be called here. It will be used within the KF class where its precise form is unknown). The library would be used by an engineer who would provide a specific function to be used as the measurement model, so he/she would specify the name of the function and its arguments during the construction of the KF class, and it would be expected that this would be a regular, non-templated, function. I only used a simple lambda function in this example because it fitted neatly on one line and it was also used in the example I was following.