Suppose I want to have a function double adapter(double), is there a general way to compose it with a boost::function<double(...)> functor to produce another boost::function<double(...)> functor2 where functor2(...) == adapter(functor(...))? In particular, it would be cool if there was a way to do this without using C++11.

edit To clarify, I'm interested in knowing if there's a way to write something that can handle any boost::function<double(...)>, i.e. ones that have different length signatures without having to copy and paste multiple times for 1, 2, 3, etc. arguments.

有帮助吗?

解决方案

Without c++11, there are a significant number of complexities, including the varadic arguments and forwarding.

With C++11, it can be done, mostly by specializaing std::is_bind_expression. When this function object is used in a bind, it calls the function object that was stored with all of the arguments that were provided during the call to the bound function object. Note, this works with any function object, not just std::function.

This works with 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;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top