2012-09-13 42 views
1

假设我想要一个函数double adapter(double),是否有一种通用的方法来编写它与boost::function<double(...)> functor来产生另一个boost::function<double(...)> functor2其中functor2(...) == adapter(functor(...))?特别是,如果有一种方法可以在不使用C++ 11的情况下执行此操作,那将会很酷。Boost函数组合

编辑为了澄清,我想知道是否有写一些东西,可以处理任何boost::function<double(...)>,即那些具有不同长度的签名,而不必多次为1复制和粘贴,2,3路等参数。

+0

支持不同数量的参数不是在C++ 03公园散步。 –

回答

2

没有C++ 11,有很多复杂性,包括可变参数和转发。使用C++ 11,可以完成它,主要是通过专门的std::is_bind_expression来完成。当此函数对象用于绑定时,它将调用与调用绑定函数对象期间提供的所有参数一起存储的函数对象。请注意,这适用于任何函数对象,而不仅仅是std::function

这适用于GCC 4.7。

#include <functional> 
#include <utility> 
#include <type_traits> 

namespace detail 
{ 
template<typename Func> 
struct compose_functor 
{ 

    Func f; 

    explicit compose_functor(const Func& f) : f(f) {}; 

    template<typename... Args> 
    auto operator()(Args&&... args) const -> decltype(f(std::forward<Args>(args)...)) 
    { 
    return f(std::forward<Args>(args)...); 
    } 

}; 

} 

template<typename Func> 
detail::compose_functor 
<Func> compose(Func f) 
{ 
    return detail::compose_functor<Func>(f); 
} 


namespace std 
{ 
    template<typename T> 
    struct is_bind_expression< detail::compose_functor<T> > : true_type {}; 
} 
#include <numeric> 

int adapter(double d) 
{ 
    return (int)d; 
} 

int main() 
{ 
    std::function<int(double)> f1 = std::bind(adapter, compose(std::negate<double>())); 
    std::function<int(double, double)> f2 = std::bind(adapter, compose(std::plus<double>())); 

    // 1.5 -> -1.5 -> -1 
    std::cout << f1(1.5) << std::endl; 
    // 2.3+4.5 = 6.8 -> 6 
    std::cout << f2(2.3, 4.5) << std::endl; 
}