#ifndef CORE_UTILITY_HPP #define CORE_UTILITY_HPP #include #include #include namespace core { inline namespace v2 { template constexpr T&& forward (remove_reference_t& t) noexcept { return static_cast(t); } template constexpr T&& forward (remove_reference_t&& t) noexcept { return static_cast(t); } template constexpr auto move (T&& t) noexcept -> decltype( static_cast&&>(t) ) { return static_cast&&>(t); } template using integer_sequence = meta::integer_sequence; template <::std::size_t... I> using index_sequence = integer_sequence<::std::size_t, I...>; template using make_integer_sequence = typename meta::iota::type; template <::std::size_t N> using make_index_sequence = make_integer_sequence<::std::size_t, N>; template using index_sequence_for = make_index_sequence; template <::std::size_t N, class T, class... Ts> constexpr auto value_at (T&& value, Ts&&...) -> enable_if_t< N == 0 and N < (sizeof...(Ts) + 1), decltype(::core::forward(value)) > { return ::core::forward(value); } template <::std::size_t N, class T, class... Ts> constexpr auto value_at (T&&, Ts&&... values) -> enable_if_t< N != 0 and N < (sizeof...(Ts) + 1), meta::get, N> > { return value_at(::core::forward(values)...); } template struct scope_guard final { static_assert( ::std::is_nothrow_move_constructible::value, "Given type must be nothrow move constructible" ); explicit scope_guard (Callable callable) noexcept : callable { ::core::move(callable) }, dismissed { false } { } scope_guard (scope_guard const&) = delete; scope_guard (scope_guard&&) = default; scope_guard () = delete; ~scope_guard () noexcept { if (not this->dismissed) { callable(); } } scope_guard& operator = (scope_guard const&) = delete; scope_guard& operator = (scope_guard&&) = default; void dismiss () noexcept { this->dismissed = true; } private: Callable callable; bool dismissed; }; template auto make_scope_guard(Callable&& callable) -> scope_guard> { return scope_guard> { ::core::forward(callable) }; } template T exchange (T& obj, U&& value) noexcept( meta::all< ::std::is_nothrow_move_constructible, ::std::is_nothrow_assignable, U> >() ) { T old = ::core::move(obj); obj = ::core::forward(value); return old; } inline ::std::uintptr_t as_int (void const* ptr) noexcept { return reinterpret_cast<::std::uintptr_t>(ptr); } template void const* as_void (T const* ptr) { return static_cast(ptr); } template void* as_void (T* ptr) { return static_cast(ptr); } template void const* as_void (T const& ref) { return as_void(::std::addressof(ref)); } template void* as_void (T& ref) { return as_void(::std::addressof(ref)); } template constexpr auto as_under(E e) noexcept -> meta::when< std::is_enum::value, underlying_type_t > { return static_cast>(e); } template struct capture final { static_assert(::std::is_move_constructible::value, "T must be movable"); using value_type = T; using reference = add_lvalue_reference_t; using pointer = add_pointer_t; capture (T&& data) : data { core::move(data) } { } capture (capture&&) = default; capture (capture& that) : data { core::move(that.data) } { } capture () = delete; capture& operator = (capture const&) = delete; capture& operator = (capture&&) = delete; operator reference () const noexcept { return this->get(); } reference operator * () const noexcept { return this->get(); } pointer operator -> () const noexcept { return ::std::addressof(this->get()); } reference get () const noexcept { return this->data; } private: value_type data; }; template auto make_capture (remove_reference_t& ref) -> capture { return capture { core::move(ref) }; } template auto make_capture (remove_reference_t&& ref) -> capture { return capture { core::move(ref) }; } struct erased_type { }; }} /* namespace core::v2 */ #endif /* CORE_UTILITY_HPP */