使用 boost::bind 但允许传递任何其他参数

Using boost::bind but allowing any additional parameters to be passed through

本文关键字:任何 其他 许传递 参数 boost bind 使用      更新时间:2023-10-16

我正在整理一个"简单"的模板类。它提供了一个接口,用于对数据库执行某些操作,因此还有其他成员(主要用于对容器成员进行操作(。但是,出于我们的目的,模板类如下所示:

template<typename T, //the type of objects the class will be manipulating
         typename S> //the signature of the function the class will be using
FunctionHandler
{
private:
    std::vector<T> container;
    boost::function<S> the_operation;
    SomeClass* pSC; //a database connection; implementation unimportant
    //some other members--not relevant here
public:
    boost::function<???> Operate;
    FunctionHandler(boost::function<S> the_operation_)
        : the_operation(the_operation_)
    {
        Operate = boost::bind(the_operation, pSC, std::back_inserter<std::vector<T> >,
                              /*infer that all other parameters passed to Operate
                                should be passed through to the_operation*/);
    }
    //other peripheral functions
}

我的问题是双重的。

  1. 我应该把什么作为Operate的模板参数,即什么替换了???
  2. 我如何告诉boost::bind它应该将提供给Operate的任何其他参数传递给the_operation?换句话说,对于一些看起来像void (SomeClass*, std::back_insert_iterator<std::vector<T> >, int, bool)的任意函数签名S和其他一些看起来像void (SomeClass*, std::back_insert_iterator<std::vector<T> >, double, double, bool)的任意函数签名O,我如何编写这个模板类,以便Operate第一个签名为 void (int, bool),第二个签名为 void (double, double, bool),并将其值传递给the_operation的第 3-N 个参数?

在我的搜索中,我找不到任何像这样的问题。

为什么还要使用绑定?没有它,我们可以得到同样的效果。我正在使用Iter作为模板,但您可以使用正确的类型来填充它:

template <typename S, typename Iter>
class Operator
{
    boost::function<S> func_;
    SomeClass* cls_;
    Iter iter_;
public:
    Operator(function<S> func, SomeClass* cls, Iter iter)
    : func_(func), cls_(cls), iter_(iter)
    { }
    // one for each # of args
    typename boost::result_of<
        boost::function<S>(SomeClass*, Iter)
    >::type operator()() const {
        return func_(cls_, iter_);
    }
    template <typename A>
    typename boost::result_of<
        boost::function<S>(SomeClass*, Iter, A)
    >::type operator()(A a) const {
        return func_(cls_, iter_, a);
    }
    template <typename A, typename B>
    typename boost::result_of<
        boost::function<S>(SomeClass*, Iter, A, B)
    >::type operator()(A a, B b) const {
        return func_(cls_, iter_, a, b);
    }
    // etc.
};

我们正在制作所有operator(),但它们只有在被调用时才会被实例化 - 所以只要你调用正确的一个(对于任何解决方案,你无论如何都必须这样做(,这就可以了。

不幸的是,

没有办法"推断"所有其他参数。您必须指定所有正确的占位符。从 C++03 开始,我们只能使用大量的模板专业化。

template <typename S> struct Operate;
template <typename R, typename Iter>
struct Operate<R(SomeClass*, Iter)>
{
    using namespace boost;
    function<R()> op_;
    Operator(function<R(SomeClass*, Iter)> op, SomeClass* cls, Iter iter)
    : op_(bind(op, cls, iter))
    { }
};
template <typename R, typename Iter, typename A>
struct Operate<R(SomeClass*, Iter, A)>
{
    using namespace boost;
    function<R(A)> op_;
    Operator(function<R(SomeClass*, Iter, A)> op, SomeClass* cls, Iter iter)
    : op_(bind(op, cls, iter, _1))
    { }
};
template <typename R, typename Iter, typename A, typename B>
struct Operate<R(SomeClass*, Iter, A, B)>
{
    using namespace boost;
    function<R(A, B)> op_;
    Operator(function<R(SomeClass*, Iter, A, B)> op, SomeClass* cls, Iter iter)
    : op_(bind(op, cls, iter, _1, _2))
    { }
};
// etc.

这很冗长,但如果你不能使用 C++11,我不知道你还能做什么。其中,为了完整起见:

template <typename R, typename Iter, typename... Extra>
struct Operator<R(SomeClass*, Iter, Extra...)>
{
    std::function<R(SomeClass*, Iter, Extra...)> op_;
    SomeClass* cls_;
    Iter iter_;
    Operator(function<R(SomeClass*, Iter, Extra...)> op, SomeClass* cls, Iter iter)
    : op_(op), cls_(cls), iter_(iter)
    { }
    R operator()(Extra... args) const {
        return op_(cls_, iter_, args...);
    }
};

我对提升的了解。不幸的是,MPL 非常有限,因此我认为这不是解决从函数类型中删除前两个参数类型的问题的最好方法。

#include <boost/function_types/components.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/erase.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/advance.hpp>
#include <boost/mpl/int.hpp>
template<typename F, int N>
class remove_first_N_param_types
{
        typedef typename boost::function_types::components<F>::type
    components;
        typedef typename boost::mpl::begin<components>::type
    beg;
        typedef typename boost::mpl::advance<beg, boost::mpl::int_<1  >>::type
    beg_param;
        typedef typename boost::mpl::advance<beg, boost::mpl::int_<1+N>>::type
    beg_param_plus_N;
        typedef typename boost::mpl::erase<components,
                                           beg_param, beg_param_plus_N>::type
    erased_first_N_params;
public:
        typedef typename boost::function_types::
        function_type<erased_first_N_params>::type
    type;
};

现场示例

相关文章: