Created
August 8, 2021 23:44
-
-
Save AnthonyMikh/fbe95fdbb9a5b68e9b0c649a90dba3f1 to your computer and use it in GitHub Desktop.
Инициализация массивов a la C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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