#ifndef BOOST_BIND_BIND_HPP_INCLUDED #define BOOST_BIND_BIND_HPP_INCLUDED // MS compatible compilers support #pragma once #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif // // bind.hpp - binds function objects to arguments // // Copyright 2001-2005, 2024 Peter Dimov // Copyright 2001 David Abrahams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/bind for documentation. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable: 4512) // assignment operator could not be generated #endif namespace boost { template class weak_ptr; namespace _bi // implementation details { // ref_compare template bool ref_compare( T const & a, T const & b ) { return a == b; } template bool ref_compare( arg const &, arg const & ) { return true; } template bool ref_compare( arg (*) (), arg (*) () ) { return true; } template bool ref_compare( reference_wrapper const & a, reference_wrapper const & b ) { return a.get_pointer() == b.get_pointer(); } // bind_t forward declaration for listN template class bind_t; template bool ref_compare( bind_t const & a, bind_t const & b ) { return a.compare( b ); } // value template class value { public: value(T const & t): t_(t) {} T & get() { return t_; } T const & get() const { return t_; } bool operator==(value const & rhs) const { return t_ == rhs.t_; } private: T t_; }; // ref_compare for weak_ptr template bool ref_compare( value< weak_ptr > const & a, value< weak_ptr > const & b ) { return !(a.get() < b.get()) && !(b.get() < a.get()); } // type template class type {}; // unwrap template struct unwrapper { static inline F & unwrap( F & f, long ) { return f; } template static inline F2 & unwrap( reference_wrapper rf, int ) { return rf.get(); } template static inline _mfi::dm unwrap( R T::* pm, int ) { return _mfi::dm( pm ); } }; // list template struct accept_lambda { V& v_; explicit accept_lambda( V& v ): v_( v ) {} template void operator()( A& a ) const { visit_each( v_, a, 0 ); } }; struct equal_lambda { bool result; equal_lambda(): result( true ) {} template void operator()( A1& a1, A2& a2 ) { result = result && ref_compare( a1, a2 ); } }; struct logical_and; struct logical_or; template class list { private: typedef std::tuple data_type; data_type data_; public: list( A... a ): data_( a... ) {} #if defined(BOOST_MSVC) # pragma warning( push ) # pragma warning( disable: 4100 ) // unreferenced formal parameter 'a2' #endif template R call_impl( type, F & f, A2 & a2, _bi::index_sequence ) { return unwrapper::unwrap( f, 0 )( a2[ std::get( data_ ) ]... ); } template R call_impl( type, F & f, A2 & a2, _bi::index_sequence ) const { return unwrapper::unwrap( f, 0 )( a2[ std::get( data_ ) ]... ); } template void call_impl( type, F & f, A2 & a2, _bi::index_sequence ) { unwrapper::unwrap( f, 0 )( a2[ std::get( data_ ) ]... ); } template void call_impl( type, F & f, A2 & a2, _bi::index_sequence ) const { unwrapper::unwrap( f, 0 )( a2[ std::get( data_ ) ]... ); } #if defined(BOOST_MSVC) # pragma warning( pop ) #endif // template R operator()( type, F & f, A2 & a2 ) { return call_impl( type(), f, a2, _bi::index_sequence_for() ); } template R operator()( type, F & f, A2 & a2 ) const { return call_impl( type(), f, a2, _bi::index_sequence_for() ); } // template bool operator()( type, logical_and & /*f*/, A2 & a2 ) { static_assert( sizeof...(A) == 2, "operator&& must have two arguments" ); return a2[ std::get<0>( data_ ) ] && a2[ std::get<1>( data_ ) ]; } template bool operator()( type, logical_and const & /*f*/, A2 & a2 ) const { static_assert( sizeof...(A) == 2, "operator&& must have two arguments" ); return a2[ std::get<0>( data_ ) ] && a2[ std::get<1>( data_ ) ]; } template bool operator()( type, logical_or & /*f*/, A2 & a2 ) { static_assert( sizeof...(A) == 2, "operator|| must have two arguments" ); return a2[ std::get<0>( data_ ) ] || a2[ std::get<1>( data_ ) ]; } template bool operator()( type, logical_or const & /*f*/, A2 & a2 ) const { static_assert( sizeof...(A) == 2, "operator|| must have two arguments" ); return a2[ std::get<0>( data_ ) ] || a2[ std::get<1>( data_ ) ]; } // template void accept( V & v ) const { _bi::tuple_for_each( accept_lambda( v ), data_ ); } bool operator==( list const & rhs ) const { return _bi::tuple_for_each( equal_lambda(), data_, rhs.data_ ).result; } }; // bind_t template class rrlist { private: using args_type = std::tuple; using data_type = std::tuple; data_type data_; template friend class rrlist; public: explicit rrlist( A&... a ): data_( a... ) {} template explicit rrlist( rrlist const& r ): data_( r.data_ ) {} template typename std::tuple_element::type&& operator[] ( boost::arg ) const { return std::forward::type>( std::get( data_ ) ); } template typename std::tuple_element::type&& operator[] ( boost::arg(*)() ) const { return std::forward::type>( std::get( data_ ) ); } template T & operator[] ( _bi::value & v ) const { return v.get(); } template T const & operator[] ( _bi::value const & v ) const { return v.get(); } template T & operator[] ( reference_wrapper const & v ) const { return v.get(); } template typename result_traits::type operator[] ( bind_t & b ) const { rrlist a2( *this ); return b.eval( a2 ); } template typename result_traits::type operator[] ( bind_t const & b ) const { rrlist a2( *this ); return b.eval( a2 ); } }; template class bind_t { private: F f_; L l_; public: typedef typename result_traits::type result_type; typedef bind_t this_type; bind_t( F f, L const & l ): f_( std::move(f) ), l_( l ) {} // template result_type operator()( A&&... a ) { rrlist a2( a... ); return l_( type(), f_, a2 ); } template result_type operator()( A&&... a ) const { rrlist a2( a... ); return l_( type(), f_, a2 ); } // template result_type eval( A & a ) { return l_( type(), f_, a ); } template result_type eval( A & a ) const { return l_( type(), f_, a ); } template void accept( V & v ) const { using boost::visit_each; visit_each( v, f_, 0 ); l_.accept( v ); } bool compare( this_type const & rhs ) const { return ref_compare( f_, rhs.f_ ) && l_ == rhs.l_; } }; // function_equal template bool function_equal( bind_t const & a, bind_t const & b ) { return a.compare(b); } // add_value template< class T, int I > struct add_value_2 { typedef boost::arg type; }; template< class T > struct add_value_2< T, 0 > { typedef _bi::value< T > type; }; template struct add_value { typedef typename add_value_2< T, boost::is_placeholder< T >::value >::type type; }; template struct add_value< value > { typedef _bi::value type; }; template struct add_value< reference_wrapper > { typedef reference_wrapper type; }; template struct add_value< arg > { typedef boost::arg type; }; template struct add_value< arg (*) () > { typedef boost::arg (*type) (); }; template struct add_value< bind_t > { typedef bind_t type; }; // list_av template struct list_av { typedef list< typename add_value::type... > type; }; // operator! struct logical_not { template bool operator()(V const & v) const { return !v; } }; template bind_t< bool, logical_not, list< bind_t > > operator! (bind_t const & f) { typedef list< bind_t > list_type; return bind_t ( logical_not(), list_type(f) ); } // relational operators #define BOOST_BIND_OPERATOR( op, name ) \ \ struct name \ { \ template bool operator()(V const & v, W const & w) const { return v op w; } \ }; \ \ template \ bind_t< bool, name, list< bind_t, typename add_value::type > > \ operator op (bind_t const & f, A2 a2) \ { \ typedef typename add_value::type B2; \ typedef list< bind_t, B2> list_type; \ return bind_t ( name(), list_type(f, a2) ); \ } BOOST_BIND_OPERATOR( ==, equal ) BOOST_BIND_OPERATOR( !=, not_equal ) BOOST_BIND_OPERATOR( <, less ) BOOST_BIND_OPERATOR( <=, less_equal ) BOOST_BIND_OPERATOR( >, greater ) BOOST_BIND_OPERATOR( >=, greater_equal ) BOOST_BIND_OPERATOR( &&, logical_and ) BOOST_BIND_OPERATOR( ||, logical_or ) #undef BOOST_BIND_OPERATOR // visit_each template void visit_each( V & v, value const & t, int ) { using boost::visit_each; visit_each( v, t.get(), 0 ); } template void visit_each( V & v, bind_t const & t, int ) { t.accept( v ); } } // namespace _bi // is_bind_expression template< class T > struct is_bind_expression { enum _vt { value = 0 }; }; template< class R, class F, class L > struct is_bind_expression< _bi::bind_t< R, F, L > > { enum _vt { value = 1 }; }; // bind #ifndef BOOST_BIND #define BOOST_BIND bind #endif // generic function objects #if !BOOST_WORKAROUND(__GNUC__, < 6) template _bi::bind_t::type> BOOST_BIND( F f, A... a ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a... ) ); } #else // g++ 4.x (and some 5.x) consider boost::bind( &X::f ) // ambiguous if the variadic form above is used template _bi::bind_t::type> BOOST_BIND( F f ) { typedef typename _bi::list_av<>::type list_type; return _bi::bind_t( std::move(f), list_type() ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2, A3 a3 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2, a3 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2, A3 a3, A4 a4 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2, a3, a4 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2, a3, a4, a5 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2, a3, a4, a5, a6 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2, a3, a4, a5, a6, a7 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2, a3, a4, a5, a6, a7, a8 ) ); } template _bi::bind_t::type> BOOST_BIND( F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ); } #endif // generic function objects, alternative syntax template _bi::bind_t::type> BOOST_BIND( boost::type, F f, A... a ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t( std::move(f), list_type( a... ) ); } // adaptable function objects template _bi::bind_t<_bi::unspecified, F, typename _bi::list_av::type> BOOST_BIND( F f, A... a ) { typedef typename _bi::list_av::type list_type; return _bi::bind_t<_bi::unspecified, F, list_type>( std::move(f), list_type( a... ) ); } // function pointers #define BOOST_BIND_CC #define BOOST_BIND_ST #define BOOST_BIND_NOEXCEPT #include # if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) # undef BOOST_BIND_NOEXCEPT # define BOOST_BIND_NOEXCEPT noexcept # include # endif #undef BOOST_BIND_CC #undef BOOST_BIND_ST #undef BOOST_BIND_NOEXCEPT #if defined(BOOST_BIND_ENABLE_STDCALL) && !defined(_M_X64) #define BOOST_BIND_CC __stdcall #define BOOST_BIND_ST #define BOOST_BIND_NOEXCEPT #include #undef BOOST_BIND_CC #undef BOOST_BIND_ST #undef BOOST_BIND_NOEXCEPT #endif #if defined(BOOST_BIND_ENABLE_FASTCALL) && !defined(_M_X64) #define BOOST_BIND_CC __fastcall #define BOOST_BIND_ST #define BOOST_BIND_NOEXCEPT #include #undef BOOST_BIND_CC #undef BOOST_BIND_ST #undef BOOST_BIND_NOEXCEPT #endif #ifdef BOOST_BIND_ENABLE_PASCAL #define BOOST_BIND_ST pascal #define BOOST_BIND_CC #define BOOST_BIND_NOEXCEPT #include #undef BOOST_BIND_ST #undef BOOST_BIND_CC #undef BOOST_BIND_NOEXCEPT #endif // member function pointers #define BOOST_BIND_MF_NAME(X) X #define BOOST_BIND_MF_CC #define BOOST_BIND_MF_NOEXCEPT #include #include # if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) # undef BOOST_BIND_MF_NOEXCEPT # define BOOST_BIND_MF_NOEXCEPT noexcept # include # include # endif #undef BOOST_BIND_MF_NAME #undef BOOST_BIND_MF_CC #undef BOOST_BIND_MF_NOEXCEPT #if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64) #define BOOST_BIND_MF_NAME(X) X##_cdecl #define BOOST_BIND_MF_CC __cdecl #define BOOST_BIND_MF_NOEXCEPT #include #include #undef BOOST_BIND_MF_NAME #undef BOOST_BIND_MF_CC #undef BOOST_BIND_MF_NOEXCEPT #endif #if defined(BOOST_MEM_FN_ENABLE_STDCALL) && !defined(_M_X64) #define BOOST_BIND_MF_NAME(X) X##_stdcall #define BOOST_BIND_MF_CC __stdcall #define BOOST_BIND_MF_NOEXCEPT #include #include #undef BOOST_BIND_MF_NAME #undef BOOST_BIND_MF_CC #undef BOOST_BIND_MF_NOEXCEPT #endif #if defined(BOOST_MEM_FN_ENABLE_FASTCALL) && !defined(_M_X64) #define BOOST_BIND_MF_NAME(X) X##_fastcall #define BOOST_BIND_MF_CC __fastcall #define BOOST_BIND_MF_NOEXCEPT #include #include #undef BOOST_BIND_MF_NAME #undef BOOST_BIND_MF_CC #undef BOOST_BIND_MF_NOEXCEPT #endif // data member pointers namespace _bi { template< class Pm, int I > struct add_cref; template< class M, class T > struct add_cref< M T::*, 0 > { typedef M type; }; template< class M, class T > struct add_cref< M T::*, 1 > { #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable:4180) #endif typedef M const & type; #ifdef BOOST_MSVC #pragma warning(pop) #endif }; template< class R, class T > struct add_cref< R (T::*) (), 1 > { typedef void type; }; template< class R, class T > struct add_cref< R (T::*) () const, 1 > { typedef void type; }; #if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) template< class R, class T > struct add_cref< R (T::*) () const noexcept, 1 > { typedef void type; }; #endif // __cpp_noexcept_function_type template struct isref { enum value_type { value = 0 }; }; template struct isref< R& > { enum value_type { value = 1 }; }; template struct isref< R* > { enum value_type { value = 1 }; }; template struct dm_result { typedef typename add_cref< Pm, 1 >::type type; }; template struct dm_result< Pm, bind_t > { typedef typename bind_t::result_type result_type; typedef typename add_cref< Pm, isref< result_type >::value >::type type; }; } // namespace _bi template< class A1, class M, class T > _bi::bind_t< typename _bi::dm_result< M T::*, A1 >::type, _mfi::dm, typename _bi::list_av::type > BOOST_BIND( M T::*f, A1 a1 ) { typedef typename _bi::dm_result< M T::*, A1 >::type result_type; typedef _mfi::dm F; typedef typename _bi::list_av::type list_type; return _bi::bind_t< result_type, F, list_type >( F( f ), list_type( a1 ) ); } } // namespace boost #ifndef BOOST_BIND_NO_PLACEHOLDERS # include #endif #ifdef BOOST_MSVC # pragma warning(default: 4512) // assignment operator could not be generated # pragma warning(pop) #endif #endif // #ifndef BOOST_BIND_BIND_HPP_INCLUDED