// https://github.com/WG21-SG14/SG14/blob/master/SG14/inplace_function.h // Doc: https://github.com/WG21-SG14/SG14/blob/master/Docs/Proposals/NonAllocatingStandardFunction.pdf /* * Boost Software License - Version 1.0 - August 17th, 2003 * * Permission is hereby granted, free of charge, to any person or organization * obtaining a copy of the software and accompanying documentation covered by * this license (the "Software") to use, reproduce, display, distribute, * execute, and transmit the Software, and to prepare derivative works of the * Software, and to permit third-parties to whom the Software is furnished to * do so, all subject to the following: * * The copyright notices in the Software and this entire statement, including * the above license grant, this restriction and the following disclaimer, * must be included in all copies of the Software, in whole or in part, and * all derivative works of the Software, unless such copies or derivative * works are solely in the form of machine-executable object code generated by * a source language processor. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #pragma once #include <type_traits> #include <utility> #include <functional> #ifndef SG14_INPLACE_FUNCTION_THROW #define SG14_INPLACE_FUNCTION_THROW(x) … #endif namespace stdext { namespace inplace_function_detail { static constexpr size_t InplaceFunctionDefaultCapacity = …; #ifndef SG14_USE_STD_ALIGNED_STORAGE // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61458 // MSVC 32-bit has the same bug. // libc++ and MSVC 64-bit seem to work fine right now, but why run the risk? template <size_t Cap> union aligned_storage_helper { … }; template <size_t Cap, size_t Align = alignof(aligned_storage_helper<Cap>)> struct aligned_storage { … }; aligned_storage_t; static_assert …; static_assert …; #else using std::aligned_storage; using std::aligned_storage_t; static_assert(sizeof(std::aligned_storage_t<sizeof(void*)>) == sizeof(void*), "C"); static_assert(alignof(std::aligned_storage_t<sizeof(void*)>) == alignof(void*), "D"); #endif template <class T> struct wrapper { … }; template <class R, class... Args> struct vtable { … }; empty_vtable; template <size_t DstCap, size_t DstAlign, size_t SrcCap, size_t SrcAlign> struct is_valid_inplace_dst : std::true_type { … }; // C++11 MSVC compatible implementation of std::is_invocable_r. template <class R> void accept(R); template <class, class R, class F, class... Args> struct is_invocable_r_impl : std::false_type { … }; is_invocable_r_impl<decltype(std::declval<F>()(std::declval<Args>()...) , void()), void, F, Args...>; is_invocable_r_impl<decltype(std::declval<F>()(std::declval<Args>()...) , void()), const void, F, Args...>; is_invocable_r_impl<decltype(accept<R>(std::declval<F>()(std::declval<Args>()...))), R, F, Args...>; is_invocable_r; } // namespace inplace_function_detail template <class Signature, size_t Capacity = inplace_function_detail::InplaceFunctionDefaultCapacity, size_t Alignment = alignof(inplace_function_detail::aligned_storage_t<Capacity>)> class inplace_function; // unspecified namespace inplace_function_detail { template <class> struct is_inplace_function : std::false_type { … }; is_inplace_function<inplace_function<Sig, Cap, Align>>; } // namespace inplace_function_detail inplace_function<R (Args...), Capacity, Alignment>; } // namespace stdext