// -*- C++ -*- //===------------------------ functional ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // STL common functionality // // Some aspects of STL are core language concepts that should be used from all C++ code, regardless // of whether exceptions are enabled in the component. Common library code that expects to be used // from exception-free components want these concepts, but including STL headers directly introduces // friction as it requires components not using STL to declare their STL version. Doing so creates // ambiguity around whether STL use is safe in a particular component and implicitly brings in // a long list of headers (including ) which can create further ambiguity around throwing new // support (some routines pulled in may expect it). Secondarily, pulling in these headers also has // the potential to create naming conflicts or other implied dependencies. // // To promote the use of these core language concepts outside of STL-based binaries, this file is // selectively pulling those concepts *directly* from corresponding STL headers. The corresponding // "std::" namespace STL functions and types should be preferred over these in code that is bound to // STL. The implementation and naming of all functions are taken directly from STL, instead using // "wistd" (Windows Implementation std) as the namespace. // // Routines in this namespace should always be considered a reflection of the *current* STL implementation // of those routines. Updates from STL should be taken, but no "bugs" should be fixed here. // // New, exception-based code should not use this namespace, but instead should prefer the std:: implementation. // Only code that is not exception-based and libraries that expect to be utilized across both exception // and non-exception based code should utilize this functionality. #ifndef _WISTD_FUNCTIONAL_H_ #define _WISTD_FUNCTIONAL_H_ // DO NOT add *any* additional includes to this file -- there should be no dependencies from its usage #include "wistd_memory.h" #include // For __fastfail #include // For placement new #if !defined(__WI_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif #pragma warning(push) #pragma warning(disable: 4324) #pragma warning(disable: 4800) /// @cond namespace wistd // ("Windows Implementation" std) { // wistd::function // // All of the code below is in direct support of wistd::function. This class is identical to std::function // with the following exceptions: // // 1) It never allocates and is safe to use from exception-free code (custom allocators are not supported) // 2) It's slightly bigger on the stack (64 bytes, rather than 24 for 32bit) // 3) There is an explicit static-assert if a lambda becomes too large to hold in the internal buffer (rather than an allocation) template struct __invoke_void_return_wrapper { #ifndef __WI_LIBCPP_CXX03_LANG template static _Ret __call(_Args&&... __args) { return __invoke(wistd::forward<_Args>(__args)...); } #else template static _Ret __call(_Fn __f) { return __invoke(__f); } template static _Ret __call(_Fn __f, _A0& __a0) { return __invoke(__f, __a0); } template static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) { return __invoke(__f, __a0, __a1); } template static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){ return __invoke(__f, __a0, __a1, __a2); } #endif }; template <> struct __invoke_void_return_wrapper { #ifndef __WI_LIBCPP_CXX03_LANG template static void __call(_Args&&... __args) { (void)__invoke(wistd::forward<_Args>(__args)...); } #else template static void __call(_Fn __f) { __invoke(__f); } template static void __call(_Fn __f, _A0& __a0) { __invoke(__f, __a0); } template static void __call(_Fn __f, _A0& __a0, _A1& __a1) { __invoke(__f, __a0, __a1); } template static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) { __invoke(__f, __a0, __a1, __a2); } #endif }; //////////////////////////////////////////////////////////////////////////////// // FUNCTION //============================================================================== // bad_function_call __WI_LIBCPP_NORETURN inline __WI_LIBCPP_INLINE_VISIBILITY void __throw_bad_function_call() { __fastfail(7); // FAST_FAIL_FATAL_APP_EXIT } template class __WI_LIBCPP_TEMPLATE_VIS function; // undefined namespace __function { template struct __maybe_derive_from_unary_function { }; template struct __maybe_derive_from_unary_function<_Rp(_A1)> : public unary_function<_A1, _Rp> { }; template struct __maybe_derive_from_binary_function { }; template struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> : public binary_function<_A1, _A2, _Rp> { }; template __WI_LIBCPP_INLINE_VISIBILITY bool __not_null(_Fp const&) { return true; } template __WI_LIBCPP_INLINE_VISIBILITY bool __not_null(_Fp* __ptr) { return __ptr; } template __WI_LIBCPP_INLINE_VISIBILITY bool __not_null(_Ret _Class::*__ptr) { return __ptr; } template __WI_LIBCPP_INLINE_VISIBILITY bool __not_null(function<_Fp> const& __f) { return !!__f; } } // namespace __function #ifndef __WI_LIBCPP_CXX03_LANG namespace __function { template class __base; template class __base<_Rp(_ArgTypes...)> { __base(const __base&); __base& operator=(const __base&); public: __WI_LIBCPP_INLINE_VISIBILITY __base() {} __WI_LIBCPP_INLINE_VISIBILITY virtual ~__base() {} virtual void __clone(__base*) const = 0; virtual void __move(__base*) = 0; virtual void destroy() WI_NOEXCEPT = 0; virtual _Rp operator()(_ArgTypes&& ...) = 0; }; template class __func; template class __func<_Fp, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { _Fp __f_; public: __WI_LIBCPP_INLINE_VISIBILITY explicit __func(_Fp&& __f) : __f_(wistd::move(__f)) {} __WI_LIBCPP_INLINE_VISIBILITY explicit __func(const _Fp& __f) : __f_(__f) {} virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; virtual void __move(__base<_Rp(_ArgTypes...)>*); virtual void destroy() WI_NOEXCEPT; virtual _Rp operator()(_ArgTypes&& ... __arg); }; template void __func<_Fp, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const { ::new (__p) __func(__f_); } template void __func<_Fp, _Rp(_ArgTypes...)>::__move(__base<_Rp(_ArgTypes...)>* __p) { ::new (__p) __func(wistd::move(__f_)); } template void __func<_Fp, _Rp(_ArgTypes...)>::destroy() WI_NOEXCEPT { __f_.~_Fp(); } template _Rp __func<_Fp, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) { typedef __invoke_void_return_wrapper<_Rp> _Invoker; return _Invoker::__call(__f_, wistd::forward<_ArgTypes>(__arg)...); } } // __function template class __WI_LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>, public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> { // 'wistd::function' is most similar to 'inplace_function' in that it _only_ permits holding function objects // that can fit within its internal buffer. Therefore, we expand this size to accommodate space for at least 12 // pointers (__base vtable takes an additional one). static constexpr size_t __buffer_size = 13 * sizeof(void*); typedef __function::__base<_Rp(_ArgTypes...)> __base; __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS typename aligned_storage<__buffer_size>::type __buf_; __base* __f_; __WI_LIBCPP_NO_CFI static __base *__as_base(void *p) { return reinterpret_cast<__base*>(p); } template struct __callable_imp { static const bool value = is_same::value || is_convertible::type, _Rp>::value; }; template struct __callable_imp<_Fp, false> { static const bool value = false; }; template struct __callable { static const bool value = __callable_imp<_Fp, __lazy_and< integral_constant, function>::value>, __invokable<_Fp&, _ArgTypes...> >::value>::value; }; template using _EnableIfCallable = typename enable_if<__callable<_Fp>::value>::type; public: typedef _Rp result_type; // construct/copy/destroy: __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS function() WI_NOEXCEPT : __f_(0) {} __WI_LIBCPP_INLINE_VISIBILITY function(nullptr_t) WI_NOEXCEPT : __f_(0) {} function(const function&); function(function&&); template> function(_Fp); function& operator=(const function&); function& operator=(function&&); function& operator=(nullptr_t) WI_NOEXCEPT; template> function& operator=(_Fp&&); ~function(); // function modifiers: void swap(function&); // function capacity: __WI_LIBCPP_INLINE_VISIBILITY __WI_LIBCPP_EXPLICIT operator bool() const WI_NOEXCEPT {return __f_;} // deleted overloads close possible hole in the type system template bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete; template bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete; public: // function invocation: _Rp operator()(_ArgTypes...) const; // NOTE: type_info is very compiler specific, and on top of that, we're operating in a namespace other than // 'std' so all functions requiring RTTI have been removed }; template __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS function<_Rp(_ArgTypes...)>::function(const function& __f) { if (__f.__f_ == 0) __f_ = 0; else { __f_ = __as_base(&__buf_); __f.__f_->__clone(__f_); } } template __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS __WI_LIBCPP_SUPPRESS_NOEXCEPT_ANALYSIS function<_Rp(_ArgTypes...)>::function(function&& __f) { if (__f.__f_ == 0) __f_ = 0; else { __f_ = __as_base(&__buf_); __f.__f_->__move(__f_); __f.__f_->destroy(); __f.__f_ = 0; } } template template __WI_LIBCPP_SUPPRESS_NONINIT_ANALYSIS function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(0) { if (__function::__not_null(__f)) { typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _FF; static_assert(sizeof(_FF) <= sizeof(__buf_), "The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture."); __f_ = ::new((void*)&__buf_) _FF(wistd::move(__f)); } } template function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(const function& __f) { *this = nullptr; if (__f.__f_) { __f_ = __as_base(&__buf_); __f.__f_->__clone(__f_); } return *this; } template function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(function&& __f) { *this = nullptr; if (__f.__f_) { __f_ = __as_base(&__buf_); __f.__f_->__move(__f_); __f.__f_->destroy(); __f.__f_ = 0; } return *this; } template function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(nullptr_t) WI_NOEXCEPT { __base* __t = __f_; __f_ = 0; if (__t) __t->destroy(); return *this; } template template function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) { *this = nullptr; if (__function::__not_null(__f)) { typedef __function::__func::type, _Rp(_ArgTypes...)> _FF; static_assert(sizeof(_FF) <= sizeof(__buf_), "The sizeof(wistd::function) has grown too large for the reserved buffer (12 pointers). Refactor to reduce size of the capture."); __f_ = ::new((void*)&__buf_) _FF(wistd::move(__f)); } return *this; } template function<_Rp(_ArgTypes...)>::~function() { if (__f_) __f_->destroy(); } template void function<_Rp(_ArgTypes...)>::swap(function& __f) { if (wistd::addressof(__f) == this) return; if (__f_ && __f.__f_) { typename aligned_storage::type __tempbuf; __base* __t = __as_base(&__tempbuf); __f_->__move(__t); __f_->destroy(); __f_ = 0; __f.__f_->__move(__as_base(&__buf_)); __f.__f_->destroy(); __f.__f_ = 0; __f_ = __as_base(&__buf_); __t->__move(__as_base(&__f.__buf_)); __t->destroy(); __f.__f_ = __as_base(&__f.__buf_); } else if (__f_) { __f_->__move(__as_base(&__f.__buf_)); __f_->destroy(); __f_ = 0; __f.__f_ = __as_base(&__f.__buf_); } else if (__f.__f_) { __f.__f_->__move(__as_base(&__buf_)); __f.__f_->destroy(); __f.__f_ = 0; __f_ = __as_base(&__buf_); } } template _Rp function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const { if (__f_ == 0) __throw_bad_function_call(); return (*__f_)(wistd::forward<_ArgTypes>(__arg)...); } template inline __WI_LIBCPP_INLINE_VISIBILITY bool operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return !__f;} template inline __WI_LIBCPP_INLINE_VISIBILITY bool operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return !__f;} template inline __WI_LIBCPP_INLINE_VISIBILITY bool operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) WI_NOEXCEPT {return (bool)__f;} template inline __WI_LIBCPP_INLINE_VISIBILITY bool operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) WI_NOEXCEPT {return (bool)__f;} // Provide both 'swap_wil' and 'swap' since we now have two ADL scenarios that we need to work template inline __WI_LIBCPP_INLINE_VISIBILITY void swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) {return __x.swap(__y);} template inline __WI_LIBCPP_INLINE_VISIBILITY void swap_wil(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) {return __x.swap(__y);} // std::invoke template typename __invoke_of<_Fn, _Args...>::type invoke(_Fn&& __f, _Args&&... __args) __WI_NOEXCEPT_((__nothrow_invokable<_Fn, _Args...>::value)) { return wistd::__invoke(wistd::forward<_Fn>(__f), wistd::forward<_Args>(__args)...); } #else // __WI_LIBCPP_CXX03_LANG #error wistd::function and wistd::invoke not implemented for pre-C++11 #endif } /// @endcond #pragma warning(pop) #endif // _WISTD_FUNCTIONAL_H_