Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Created August 8, 2021 23:44
Show Gist options
  • Save AnthonyMikh/fbe95fdbb9a5b68e9b0c649a90dba3f1 to your computer and use it in GitHub Desktop.
Save AnthonyMikh/fbe95fdbb9a5b68e9b0c649a90dba3f1 to your computer and use it in GitHub Desktop.
Инициализация массивов a la C++
trait ConstZero {
const ZERO: Self;
}
macro_rules! impl_primitive {
($($ty:ty)*) => {
$(
impl ConstZero for $ty {
const ZERO: Self = 0;
}
)*
}
}
impl_primitive!(
i8 i16 i32 i64 i128 isize
u8 u16 u32 u64 u128 usize
);
impl ConstZero for f32 {
const ZERO: Self = 0.0;
}
impl ConstZero for f64 {
const ZERO: Self = 0.0;
}
macro_rules! impl_tuple {
() => {};
($first:ident $($ty:ident)*) => {
impl<$first, $($ty),*> ConstZero for ($first, $($ty),*)
where
$first: ConstZero,
$($ty: ConstZero,)*
{
const ZERO: Self = (
<$first as ConstZero>::ZERO,
$(<$ty as ConstZero>::ZERO),*
);
}
impl_tuple!($($ty)*);
}
}
impl_tuple!(A B C D E F G H);
impl ConstZero for () {
const ZERO: Self = ();
}
impl ConstZero for bool {
const ZERO: Self = false;
}
impl<'a> ConstZero for &'a str {
const ZERO: Self = "";
}
impl<T> ConstZero for Vec<T> {
const ZERO: Self = Vec::new();
}
impl<T: ConstZero, const LEN: usize> ConstZero for [T; LEN] {
const ZERO: Self = [T::ZERO; LEN];
}
trait ArrayConstZero: ConstZero {
const ZERO: Self;
}
impl<T: ConstZero, const N: usize> ArrayConstZero for [T; N] {
const ZERO: Self = <Self as ConstZero>::ZERO;
}
trait Array {
const LEN: usize;
}
impl<T, const N: usize> Array for [T; N] {
const LEN: usize = N;
}
macro_rules! arr_init {
($($elem:expr,)* ; $len:expr) => {{
const LEN: usize = $len;
const _INIT_LEN: usize = $({stringify!($elem); 1usize} +)* 0;
const _ASSERT_NOT_TOO_MANY: [(); LEN] = [(); if LEN >= _INIT_LEN { LEN } else { _INIT_LEN }];
let mut ret = [<_ as ConstZero>::ZERO; LEN];
let mut i = 0usize;
$(
i += 1;
ret[i - 1] = $elem;
)*
ret
}};
}
macro_rules! arr_let {
(mut $name:ident: [$ty:ty; $len:expr] = [$($elem:expr,)*]) => {
let mut $name: [$ty; $len] = arr_init![$($elem,)*; $len];
};
($name:ident: [$ty:ty; $len:expr] = [$($elem:expr,)*]) => {
let $name: [$ty; $len] = arr_init![$($elem,)*; $len];
};
}
macro_rules! arr_const {
($name:ident: [$ty:ty; $len:expr] = [$($elem:expr,)*]) => {
const $name: [$ty; $len] = {
const fn init_arr() -> [$ty; $len] {
arr_init![$($elem,)*; $len]
}
init_arr()
};
};
}
#[derive(Debug)]
struct Thirteen(u32);
impl ConstZero for Thirteen {
const ZERO: Self = Self(13);
}
arr_const!(ARRAY: [Thirteen; 13] = [Thirteen(15), Thirteen(14),]);
fn main() {
println!("{:?}", ARRAY);
arr_let!(
arr: [_; 3] = [(
[vec![2u64, 3]],
(("hey",), (2i32, 3.14f64, ()), [true, true])
),]
);
let all_but_one_zeros = arr_init![128u128,; 7];
println!("{:?}", arr);
println!("{:?}", all_but_one_zeros);
// не компилируется
// let wrong = arr_init![(),; 0];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment