#ifndef BOOST_COMPAT_MOVE_ONLY_FUNCTION_HPP_INCLUDED #define BOOST_COMPAT_MOVE_ONLY_FUNCTION_HPP_INCLUDED // Copyright 2025 Christian Mazakas. // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include #include #include #include #include #include #include #if BOOST_WORKAROUND(BOOST_GCC, >= 6 * 10000) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wnonnull-compare" # pragma GCC diagnostic ignored "-Waddress" #endif namespace boost { namespace compat { template class move_only_function; template< class T > struct in_place_type_t { explicit in_place_type_t() = default; }; namespace detail { union pointers { void* pobj_; void ( *pfn_ )(); }; struct storage { // we want SBO to be large enough to store a type which can be used for delegation purposes struct delegate { void( storage::*pmfn_ )(); storage* pobj_; }; union { void* pobj_; void ( *pfn_ )(); alignas(delegate) unsigned char buf_[ sizeof(delegate) ]; }; template constexpr static bool use_sbo() noexcept { return sizeof( T ) <= sizeof( storage ) && alignof( T ) <= alignof( storage ) && std::is_nothrow_move_constructible::value; } void* addr() noexcept { return buf_; } }; template struct is_polymorphic_function : std::false_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; #if defined(__cpp_noexcept_function_type) template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; template struct is_polymorphic_function> : std::true_type { }; #endif template using is_move_only_function = is_polymorphic_function; template struct is_in_place_type_t : std::false_type { }; template struct is_in_place_type_t> : std::true_type { }; template struct nothrow_init { constexpr static bool const value = ( storage::use_sbo() && std::is_nothrow_constructible::value ) || false; }; enum class ref_quals { none, lvalue, rvalue }; template struct is_callable_from; template struct is_callable_from { using cv_VT = conditional_t, VT>; using cv_ref_VT = conditional_t< RQ == ref_quals::none, cv_VT, conditional_t< RQ == ref_quals::rvalue, add_rvalue_reference_t, add_lvalue_reference_t > >; using inv_quals_VT = conditional_t< RQ == ref_quals::none, add_lvalue_reference_t, conditional_t< RQ == ref_quals::rvalue, add_rvalue_reference_t, add_lvalue_reference_t > >; constexpr static bool const value = is_nothrow_invocable_r::value && is_nothrow_invocable_r::value; }; template struct is_callable_from { using cv_VT = conditional_t, VT>; using cv_ref_VT = conditional_t< RQ == ref_quals::none, cv_VT, conditional_t< RQ == ref_quals::rvalue, add_rvalue_reference_t, add_lvalue_reference_t > >; using inv_quals_VT = conditional_t< RQ == ref_quals::none, add_lvalue_reference_t, conditional_t< RQ == ref_quals::rvalue, add_rvalue_reference_t, add_lvalue_reference_t > >; constexpr static bool const value = is_invocable_r::value && is_invocable_r::value; }; inline std::nullptr_t get_first_arg() { return nullptr; } template T&& get_first_arg( T&& t, CArgs&& ... ) { return std::forward( t ); } template bool is_nullary_arg( Ts&&... ) { return false; } template< class F, class VT = decay_t, enable_if_t< std::is_member_pointer::value || is_move_only_function::value, int> = 0 > bool is_nullary_arg( F&& f ) { return f == nullptr; } template< class F, class VT = decay_t, enable_if_t< std::is_function>::value, int> = 0 > bool is_nullary_arg( F f ) { return f == nullptr; } template struct mo_invoke_function_holder { static R invoke_function( storage s, Args&&... args) noexcept( NoEx ) { auto f = reinterpret_cast( s.pfn_ ); return compat::invoke_r( f, std::forward( args )... ); } }; template struct mo_invoke_object_holder { static R invoke_object( storage s, Args&&... args ) noexcept( NoEx ) { using T = remove_reference_t; using cv_T = conditional_t, T>; using cv_ref_T = conditional_t< RQ == ref_quals::none, add_lvalue_reference_t, conditional_t< RQ == ref_quals::rvalue, add_rvalue_reference_t, add_lvalue_reference_t > >; return compat::invoke_r( static_cast( *static_cast( s.pobj_ ) ), std::forward( args )... ); } }; template struct mo_invoke_local_holder { static R invoke_local( storage s, Args&&... args ) noexcept( NoEx ) { using T = remove_reference_t; using cv_T = conditional_t, T>; using cv_ref_T = conditional_t< RQ == ref_quals::none, add_lvalue_reference_t, conditional_t< RQ == ref_quals::rvalue, add_rvalue_reference_t, add_lvalue_reference_t > >; return compat::invoke_r( static_cast( *static_cast( s.addr() ) ), std::forward( args )... ); } }; enum class op_type { move, destroy }; template struct move_only_function_base { move_only_function_base() = default; move_only_function_base( move_only_function_base&& rhs ) noexcept { manager_ = rhs.manager_; manager_( op_type::move, s_, &rhs.s_ ); invoke_ = rhs.invoke_; rhs.invoke_ = nullptr; rhs.manager_ = &manage_empty; } ~move_only_function_base() { destroy(); } void swap( move_only_function_base& rhs ) noexcept { // to properly swap with storages, we need to treat the destination storage // the same as the source storage, which means that we need to use the // source manager_'s move operation storage s; rhs.manager_( op_type::move, s, &rhs.s_ ); manager_( op_type::move, rhs.s_, &s_ ); rhs.manager_( op_type::move, s_, &s ); std::swap( manager_, rhs.manager_ ); std::swap( invoke_, rhs.invoke_ ); } move_only_function_base& operator=( move_only_function_base&& rhs ) { destroy(); manager_ = rhs.manager_; manager_( op_type::move, s_, &rhs.s_ ); invoke_ = rhs.invoke_; rhs.invoke_ = nullptr; rhs.manager_ = &manage_empty; return *this; } move_only_function_base& operator=( std::nullptr_t ) noexcept { destroy(); invoke_ = nullptr; manager_ = &manage_empty; return *this; } static void manage_empty( op_type, detail::storage&, detail::storage* ) { } static void manage_function( op_type op, detail::storage& s, detail::storage* src ) { switch( op ) { case op_type::move: s.pfn_ = src->pfn_; src->pfn_ = nullptr; break; default: break; } } template static void manage_object( op_type op, detail::storage& s, detail::storage* src ) { switch( op ) { case op_type::destroy: delete static_cast( s.pobj_ ); break; case op_type::move: s.pobj_ = src->pobj_; src->pobj_ = nullptr; break; default: break; } } template static void manage_local( op_type op, detail::storage& s, detail::storage* src ) { switch( op ) { case op_type::destroy: static_cast( s.addr() )->~VT(); break; case op_type::move: { VT* p = static_cast( src->addr() ); new(s.addr()) VT( std::move( *p ) ); // destruct the element here because move construction will leave the container empty // outside of this function p->~VT(); break; } default: break; } } template void move_from_compatible_base( move_only_function_base& base ) { using polymorphic_base = move_only_function_base; manager_ = base.manager_; manager_( op_type::move, s_, &base.s_ ); invoke_ = base.invoke_; base.invoke_ = nullptr; base.manager_ = &polymorphic_base::manage_empty; } template void base_init( std::true_type, F&& f ) { move_from_compatible_base( f ); } template void base_init( std::false_type, F&&... ) { } template void init( std::false_type /* is_function */, CArgs&& ...args ) { if( is_polymorphic_function::value ) { base_init( is_polymorphic_function{}, std::forward( args )... ); return; } if( !storage::use_sbo() ) { s_.pobj_ = new VT( std::forward( args )... ); invoke_ = &mo_invoke_object_holder::invoke_object; manager_ = &manage_object; } else { new( s_.addr() ) VT( std::forward( args )... ); invoke_ = &mo_invoke_local_holder::invoke_local; manager_ = &manage_local; } } template void init( std::true_type /* is_function */, CArgs ...args ) { R (*pfn)( Args... ) = get_first_arg( args... ); s_.pfn_ = reinterpret_cast( pfn ); invoke_ = &detail::mo_invoke_function_holder::invoke_function; manager_ = &manage_function; } template void init( type_identity, CArgs&& ...args ) { init( std::is_function>(), std::forward( args )... ); } void destroy() { manager_( op_type::destroy, s_, nullptr ); } explicit operator bool() const noexcept { return invoke_ != nullptr; } detail::storage s_; #if defined(__cpp_noexcept_function_type) R ( *invoke_ )( detail::storage, Args&&... ) noexcept( NoEx ) = nullptr; #else R ( *invoke_ )( detail::storage, Args&&... ) = nullptr; #endif void ( *manager_ )( op_type, detail::storage&, detail::storage* ) = &manage_empty; }; } // namespace detail template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) & { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) && { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) const { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) const & { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) const && { return this->invoke_( this->s_, std::forward( args )... ); } }; #if defined(__cpp_noexcept_function_type) template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) noexcept { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) & noexcept { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) && noexcept { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) const noexcept { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) const& noexcept { return this->invoke_( this->s_, std::forward( args )... ); } }; template class move_only_function : detail::move_only_function_base { private: template friend struct detail::move_only_function_base; using base = detail::move_only_function_base; public: move_only_function() noexcept { } move_only_function( std::nullptr_t ) noexcept : move_only_function() { } template< class F, class VT = decay_t, enable_if_t< !std::is_same>::value && !detail::is_in_place_type_t::value && detail::is_callable_from::value, int> = 0 > move_only_function( F&& f ) noexcept( detail::nothrow_init::value ) { if( detail::is_nullary_arg( std::forward( f ) ) ) return; base::init( type_identity{}, std::forward( f ) ); } template< class T, class ...CArgs, enable_if_t< std::is_constructible::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, CArgs&& ... args ) noexcept( detail::nothrow_init::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, std::forward( args )... ); } template< class T, class U, class ...CArgs, enable_if_t< std::is_constructible&, CArgs...>::value && detail::is_callable_from::value, int> = 0 > explicit move_only_function( in_place_type_t, std::initializer_list il, CArgs&& ... args ) noexcept( detail::nothrow_init&, CArgs...>::value ) { static_assert( std::is_same>::value, "T and `decay_t` must be the same" ); base::init( type_identity{}, il, std::forward( args )... ); } move_only_function( move_only_function const& ) = delete; move_only_function( move_only_function&& ) = default; ~move_only_function() = default; move_only_function& operator=( move_only_function&& rhs ) { if( this != &rhs ) { this->base::operator=( static_cast( rhs ) ); } return *this; } move_only_function& operator=( std::nullptr_t ) noexcept { this->base::operator=( nullptr ); return *this; } template move_only_function& operator=( F&& f ) { move_only_function( std::forward( f ) ).swap( *this ); return *this; } friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept { return fn.invoke_ == nullptr; } friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept { return !( fn == nullptr ); } void swap( move_only_function& rhs ) noexcept { if( this != &rhs ) { this->base::swap( rhs ); } } friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept { lhs.swap( rhs ); } explicit operator bool() const noexcept { return static_cast( *static_cast( this ) ); } R operator()( Args... args ) const&& noexcept { return this->invoke_( this->s_, std::forward( args )... ); } }; #endif } // namespace compat } // namespace boost #if BOOST_WORKAROUND(BOOST_GCC, >= 6 * 10000) # pragma GCC diagnostic pop #endif #endif // #ifndef BOOST_COMPAT_MOVE_ONLY_FUNCTION_HPP_INCLUDED