Struct without_alloc::boxed::Box
source · [−]pub struct Box<'a, T: ?Sized> { /* private fields */ }
Expand description
An allocated instance of a type.
Example
The basic usage are allocated recursive data structures. Here is a standard example using a
Bump
with 'static
storage duration as the allocator:
use without_alloc::{Box, alloc::LocalAllocLeakExt};
use static_alloc::Bump;
#[derive(Debug)]
enum List<T> {
Nil,
Cons(T, Box<'static, List<T>>),
}
static SLAB: Bump<[u8; 1024]> = Bump::uninit();
let base = SLAB.boxed(List::Nil).unwrap();
let one = SLAB.boxed(List::Cons(0, base)).unwrap();
let two = SLAB.boxed(List::Cons(1, one)).unwrap();
// We can destruct the value (not with `*` but comparable).
match Box::take(two).0 {
List::Cons(val, _) => assert_eq!(val, 1), // Got the value back.
_ => unreachable!(),
}
Downsides
Unfortunately, this Box
does not yet support unsizing. This is very unfortunate as it means
you can’t use it for type erasure.
Design
You will likely notice quickly that this has different semantics than the std::boxed::Box
.
Its inner pointer may be larger and it does not allocate nor deallocate memory on its own. This
only wraps a fully initialized Uninit
in a RAII/Drop
interface.
Of course, there is a reason for this choice. The standard Box
, storing only the raw pointer
(as a Unique
), requires its underlying allocation to have the exact same size and align
(Layout
) as the value and the layout needs to be recalculated when deallocating. Without a
dependency on an allocator it would seem that the underlying layout becomes less important and
can be thrown away but the opposite is the case. Many converters for the std::boxed::Box
rely
on being able to reallocate into a suitably constructed new allocation on will. Not having this
luxury at our disposal means there should be a mechanism to cope with mismatching allocations
anyways. So we simply store the full Uninit
provided, relying on the library user to manage
other aspects of allocation for us.
Instead, this Box
can offer additional ways to manipulate and massage the underlying
allocation. It should be possible to restore the exact allocation Box
semantics (albeit with
one usize
more space usage) via a wrapper when an allocator is available.
Implementations
sourceimpl<'a, T: ?Sized> Box<'a, T>
impl<'a, T: ?Sized> Box<'a, T>
sourcepub unsafe fn from_raw(init: Uninit<'a, T>) -> Self
pub unsafe fn from_raw(init: Uninit<'a, T>) -> Self
Create a box from an pointer to an already initialized value.
Ensures that an already initialized value is properly dropped at the end of the lifetime of
the Box
.
Safety
The pointed-to location must have already been initialized via external means. This is as
unsafe as init.as_mut()
.
Trait Implementations
sourceimpl<T> BorrowMut<T> for Box<'_, T>
impl<T> BorrowMut<T> for Box<'_, T>
sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
sourceimpl<'a, T, U: ?Sized> CoerciblePtr<U> for Box<'a, T>
impl<'a, T, U: ?Sized> CoerciblePtr<U> for Box<'a, T>
Unsize a Box, for example into a dynamic trait object.
Usage
use unsize::{Coercion, CoerceUnsize};
use without_alloc::Uninit;
use core::mem::MaybeUninit;
let mut memory: MaybeUninit<usize> = MaybeUninit::uninit();
let boxed = Box::new(0usize, Uninit::from(&mut memory));
let debug: Box<dyn core::fmt::Debug> = unsafe {
boxed.unsize(Coercion::to_debug())
};
type Pointee = T
type Pointee = T
sourcefn as_sized_ptr(&mut self) -> *mut T
fn as_sized_ptr(&mut self) -> *mut T
sourceunsafe fn replace_ptr(self, new: *mut U) -> Box<'a, U>
unsafe fn replace_ptr(self, new: *mut U) -> Box<'a, U>
sourceimpl<T: Ord> Ord for Box<'_, T>
impl<T: Ord> Ord for Box<'_, T>
1.21.0 · sourceconst fn max(self, other: Self) -> Self
const fn max(self, other: Self) -> Self
1.21.0 · sourceconst fn min(self, other: Self) -> Self
const fn min(self, other: Self) -> Self
1.50.0 · sourceconst fn clamp(self, min: Self, max: Self) -> Selfwhere
Self: PartialOrd<Self>,
const fn clamp(self, min: Self, max: Self) -> Selfwhere
Self: PartialOrd<Self>,
sourceimpl<'a, 'b, T: PartialEq> PartialEq<Box<'b, T>> for Box<'a, T>
impl<'a, 'b, T: PartialEq> PartialEq<Box<'b, T>> for Box<'a, T>
sourceimpl<'a, 'b, T: PartialOrd> PartialOrd<Box<'b, T>> for Box<'a, T>
impl<'a, 'b, T: PartialOrd> PartialOrd<Box<'b, T>> for Box<'a, T>
sourcefn partial_cmp(&self, other: &Box<'_, T>) -> Option<Ordering>
fn partial_cmp(&self, other: &Box<'_, T>) -> Option<Ordering>
sourcefn le(&self, other: &Box<'_, T>) -> bool
fn le(&self, other: &Box<'_, T>) -> bool
self
and other
) and is used by the <=
operator. Read more