元ネタ: http://d.hatena.ne.jp/Flast/20110728/1311878870
(std|boost)::bind の結果を (std|boost)::bind に渡すと,特別扱いして関数合成を行ってくれるんだけど,それ邪魔な時があるよね.
boost::bind には protect があるけど, std::bind で同様のことって出来る? って話題.
それ Variadic Templates で出来るよ!
#include <utility> template< class F > struct protect_bind_t { F f; template< class... Args > auto operator()( Args&&... args ) -> decltype( f( std::declval<Args>()... ) ) { return f( std::forward<Args>(args)... ); } template< class... Args > auto operator()( Args&&... args ) const -> decltype( f( std::declval<Args>()... ) ) { return f( std::forward<Args>(args)... ); } }; template< class F, class Result = protect_bind_t<typename std::decay<F>::type> > Result protect( F && f ) { return { std::forward<F>(f) }; } #include <iostream> #include <functional> struct some_functor { typedef bool result_type; template < typename Pred > bool operator()( Pred pred ) { return pred( 1 ); } }; int main() { using namespace std::placeholders; auto f = std::bind( some_functor(), protect( std::bind( std::less< int >(), 0, _1 ) ) ); std::cout << std::boolalpha << f() << std::endl; }
要するに bind の結果じゃなければ特別扱いされないので,ラップすれば問題ないよね,ってことです.
…と,ここまで書いて思ったけど,基本的に protect は bind の結果に対して使うしか用途がないので,この2つを合成して,
#include <utility> template< class F > struct protect_bind_t { F f; template< class... Args > auto operator()( Args&&... args ) -> decltype( f( std::declval<Args>()... ) ) { return f( std::forward<Args>(args)... ); } template< class... Args > auto operator()( Args&&... args ) const -> decltype( f( std::declval<Args>()... ) ) { return f( std::forward<Args>(args)... ); } }; #include <functional> template< class F, class... Args, class Result = protect_bind_t< decltype( std::bind( std::declval<F>(), std::declval<Args>()... ) ) > > Result protect_bind( F && f, Args&&... args ) { return { std::bind( std::forward<F>(f), std::forward<Args>(args)... ) }; } #include <iostream> struct some_functor { typedef bool result_type; template < typename Pred > bool operator()( Pred pred ) { return pred( 1 ); } }; int main() { using namespace std::placeholders; auto f = std::bind( some_functor(), protect_bind( std::less< int >(), 0, _1 ) ); std::cout << std::boolalpha << f() << std::endl; }
って書いたほうがいいかもですね.