c++ - std::bind-like function returning a std::function -


i need bind function behaves std::bind, returns appropriate specialization of std::function.

i think std::function template arguments can extracted using placeholder number function's parameter. doesn't trivial though. there implementation available already?


why need this

i want implement waterfall function semantics similar this javascript one.

here how imagine in c++:

std::function<void(const std::string &)> f = waterfall(   []( const std::function<void(int)> &cb, const std::string & ) {     ...;     cb( 1 );   },   []( const std::function<void(double, double)> &cb, int ) {     ...;     cb(0.5, 10);   },   []( double, double ) {   } ); 

in other words, waterfall take bunch of functions, each of (but last one) takes function first parameter. waterfall bind every function previous 1 (starting last one, of course), , return single function.

basically waterfall should this:

// recursion termination: `waterfall` called single functions template< typename arg > auto waterfall( const arg& first ) -> decltype( first ) {   return first; } // recursion: `waterfall` called mulitple functions template< typename arg, typename... args > ... waterfall( const arg& first, args... args ) {   return std::bind( first, waterfall(std::forward<args>(args)...) ); } 

there 3 open problems though:

  1. figuring out return type of waterfall when called multiple arguments. cannot decltype( std::bind(first, waterfall(...)) ) (because c++ doesn't allow recursively calling template function deduce type). if knew type of function (i.e. arg), that, without first argument, return type i'm looking for.
  2. i think need know number of arguments of first in order correctly std::bind it.
  3. std::bind's return type doesn't behave way want: nesting std::bind calls merges bound functions together, rather composing them.

i able bypass third point writing std::bind wrapper wraps bound function object of type t such std::is_bind_expression<t>::value == false.

for first 2 points need find out return type , arguments type of waterfall parameters. trivial if functions std::functions. simple if lambdas, classical functions, or functors single operator(): i'd need use this function_traits. i'd really pass functions bound using std::bind waterfall, without having manually cast them std::functions, because makes code way shorter , way clearer large waterfalls.

any ideas, thoughts or suggestions?

the design here of work within helper class details::waterfall 2-function waterfall style composition done in waterfall_call.

#include <iostream> #include <utility> #include <functional> #include <string.h>  namespace details { 

this more efficient if decayed outside of structure definition, reduce unique types in cases. don't care:

  template<class f0, class f1>   struct waterfall_call {     typename std::decay<f0>::type f0;     typename std::decay<f1>::type f1; 

call f0 passing f1 , args...:

    template<class...args>     auto operator()(args&&... args)const     -> typename std::result_of<f0 const&(f1 const&,args...)>::type     {       return f0( f1, std::forward<args>(args)... );     }   }; 

the center of algorithm:

  struct waterfall { 

for 2 args, use waterfall_call:

    template<class f0, class f1>     waterfall_call<f0, f1> operator()( f0&& f0, f1&& f1 )const     {       return { std::forward<f0>(f0), std::forward<f1>(f1) };     } 

for >2 args, recurse, 2 arg solution:

    template<class f0, class...fs,       class i=typename std::result_of<waterfall const&(fs...)>::type     >     auto operator()( f0&& f0, fs&&... fs )const     -> typename std::result_of< waterfall( f0, ) >::type     {       auto child = (*this)( std::forward<fs>(fs)... );       return (*this)( std::forward<f0>(f0), std::move(child) );     } 

for 1 arg, forward out decayed version of input arg:

    template<class f0>     auto operator()(f0&&f0)const     ->typename std::decay<f0>::type     {       return std::forward<f0>(f0);     }   }; } 

and waterfall delegates details::waterfall:

template<class...fs> auto waterfall(fs&&... fs ) -> typename std::result_of<details::waterfall(fs...)>::type{   return details::waterfall{}( std::forward<fs>(fs)... ); } 

live example

the other way (besides struct trick above) of getting around recursive template return type deduction limitations take parameter template type namespace of function, , pass recursive calls. enables adl lookup, can recursively find own function when deducing own return type.


Comments

Popular posts from this blog

java - Could not locate OpenAL library -

c++ - Delete matches in OpenCV (Keypoints and descriptors) -

sorting - opencl Bitonic sort with 64 bits keys -