C ++:通用函数包装器类作为非模板类​​的成员 [英] C++: Generic function wrapper class as a member of a non-template class

查看:85
本文介绍了C ++:通用函数包装器类作为非模板类​​的成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个Kalman过滤器类,该类可以接受用户提供的测量模型函数,该函数可以具有任意数量的参数。如果您不熟悉Kalman过滤器,那没关系,基本上,我有一个非模板类,该类具有一个模板化构造函数,该构造函数接收具有任意数量的任何类型的参数的函数。然后,构造函数将传递的函数分配给函数包装成员对象,该对象本身是基于可变模板类构造的。我遇到的问题是如何在不知道将传递给构造函数的函数的特定形式的情况下,将函数包装对象声明为我的Kalman过滤器类的成员?

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?

如果这不是很清楚,我深表歉意。但是,我基本上一直遵循回答这个问题,其中 auto add = make_action([](int a,int b){std :: cout< < a + b;},2,3)表示我要作为成员变量(分配在构造函数中进行)合并到我的非模板类中的功能。

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).

这是我的代码:

#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;
}

我敢肯定,如果KF课是模板类,但我真的不想这样做。我不知道Boost是否会提供某种方式来实现我想要的功能,但我会尽可能使用基于STL的解决方案。

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.

我是可变参数模板的新手,老实说,我仍然觉得有些困惑(例如,我不是100%知道Helper命名空间中的代码如何工作),因此,如果有人也可以推荐一本很好的书或网站(对于假人),能很好地解释它们,那也将不胜感激。

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.

PS如果需要的话,我在Ubuntu 14.04上使用g ++ 4.8.4。

P.S. I'm using g++ 4.8.4 on Ubuntu 14.04, if that matters.

编辑:

我忘了提到我正在尝试建立一个库。 KF类将具有许多其他功能,但这在卡尔曼滤波器的所有实现中都是标准的。每个实现的不同之处在于度量模型(和过程模型),但在此示例中并未包括在内,因为它将以与度量模型相同的方式进行处理,因此我需要能够处理任何类型的功能带有任意数量的参数,然后有一种通用的方法在后台KF类本身的各个点上调用该函数(我在此处包含的代码显示了在主函数中调用的测量模型函数,但实际上它将在确切的形式未知的KF类中将使用它)。该库将由工程师提供,该工程师将提供要用作测量模型的特定功能,因此他/她将在构造KF类时指定该功能的名称及其自变量,并且可以预期这将是常规的非模板功能。在此示例中,我仅使用了一个简单的lambda函数,因为它整齐地排列在一行上,并且在下面的示例中也使用了它。

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.

推荐答案

不清楚会给您带来什么好处,但这会使您的示例正常工作:

Not clear what good that'll do you, but this makes your example work:

#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;
}

演示

这篇关于C ++:通用函数包装器类作为非模板类​​的成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆