2014-12-20 46 views
1

我正在放在一起“简单”的模板类。它提供了一个用于在数据库上执行某些操作的界面,所以还有其他成员(主要用于在容器成员上操作)。但是,对于我们的目的,模板类看起来像这样:使用boost :: bind,但允许任何其他参数通过

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它应该通过其他参数Operatethe_operation?换句话说,对于一些任意的函数签名S,看起来像void (SomeClass*, std::back_insert_iterator<std::vector<T> >, int, bool)和看起来像void (SomeClass*, std::back_insert_iterator<std::vector<T> >, double, double, bool)我怎么写这个模板类,使得Operatevoid (int, bool)第一和void (double, double, bool)第二签名一些其他任意函数签名O,和将其值传递给the_operation的第3个参数?

在我的搜索中,我找不到任何与此相似的问题。

+0

应该如何编译器检查参数类型与函数参数类型兼容?它如何将参数类型的转换插入函数参数类型? – dyp

+0

我不知道。回答这是回答问题的一部分,不是吗?预期的用途是在编译时和运行时参数类型都与参数类型匹配。 – caps

+0

据我所知,任意类型的集合都是不可能的。当你在'boost :: function'中存储某些东西的时候,你可以删除所有关于它的信息(用于外部),并用一个接口(返回值+参数类型)替换它。 'boost :: function'似乎不支持省略号。你可以通过在'boost :: function'的函数签名中添加类似'void *'的东西来解决这个问题,然后通过这个指针传递附加参数。但是,这还不包括类型检查和转换。 – dyp

回答

2

为什么即使使用绑定?没有它,我们可以得到相同的效果。我使用Iter作为模板,但你可以在whater权类型为填充:

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() S的,但他们只会被实例化了,如果他们被调用 - 所以只要你打电话给正确的人(对于任何解决方案,你都必须),这是有效的。

+0

我需要在这里使用'boost :: result_of'吗?我无法将返回类型作为模板的另一个参数吗? – caps

+0

@caps它会是多余的。返回类型是'S'的一部分。 – Barry

+0

是的,但如果我自己传递返回类型,则不需要使用'boost :: result_of'。 “使用提升”是我的同事喜欢尽可能少做的事,因为各种各样的好坏原因。我可能会首先浮动'result_of'解决方案,我只需要知道如果没有它,是否有可能获得。 – caps

1

不幸的是,没有办法“推断”所有其余的参数。您必须指定所有正确的占位符。从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...); 
    } 
}; 
1

我对boost.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; 
}; 

Live example

+0

这给你的类型,但你将如何构造它? – Barry

+0

是的,这可以让你将'Operate'定义为'boost :: function > Operate',虽然很酷,但并未显示如何从'member_function'构造'Operate'。尽管如此,我仍然会给予这个赞赏,因为我怀疑它可能对未来的读者有用。 – caps

+0

@caps d'oh,我已经为C++ 11做了这个工作,但是我不能在C++ 03中找到一个体面的方法来做到这一点 - 只能用模仿可变参数模板的技术(类似于Barry的第一个答案)。它可以通过使用'boost :: arg '而不是指定的占位符来简化,但手动重载或专业化仍然存在,除非您使用宏。 – dyp

相关问题