2012-09-13 48 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; 
}