Skip to content

Instantly share code, notes, and snippets.

@tesaguri
Created October 9, 2020 10:46
Show Gist options
  • Save tesaguri/0cd095dcbbf4aad803394f2819169b1c to your computer and use it in GitHub Desktop.
Save tesaguri/0cd095dcbbf4aad803394f2819169b1c to your computer and use it in GitHub Desktop.
An experimental implementation of a `default` constructor for `[T; N]`
#![feature(min_const_generics)]
use std::mem::{self, MaybeUninit};
use std::ptr;
pub fn array_default<T: Default, const N: usize>() -> [T; N] {
struct Guard<T> {
dst: *mut T,
i: usize,
}
impl<T> Drop for Guard<T> {
fn drop(&mut self) {
unsafe {
let init = ptr::slice_from_raw_parts_mut(self.dst, self.i);
ptr::drop_in_place(init);
}
}
}
let mut dst: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
let mut guard = Guard {
dst: dst.as_mut_ptr(),
i: 0,
};
for dst in &mut dst {
*dst = MaybeUninit::new(T::default());
guard.i += 1;
}
mem::forget(guard);
unsafe { mem::transmute_copy::<[MaybeUninit<T>; N], [T; N]>(&dst) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(array_default::<u8, 33>(), [0; 33]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment