问题代码:
struct S();
let ss: [Option<S>; 1024] = [None; 1024];
编译器错误:
error[E0277]: the trait bound `Option<S>: std::marker::Copy` is not satisfied
------
|
68 | let ss: [Option<S>; 1024] = [None; 1024];
| ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `Option<S>`
|
= help: the following implementations were found:
<Option<T> as std::marker::Copy>
= note: the `Copy` trait is required because the repeated element will be copied
= note: this array initializer can be evaluated at compile-time, see issue #49147 <https://github.com/rust-lang/rust/issues/49147> for more information
实现一个宏来解决:
macro_rules! array_init {
($default:expr; $usize:expr)=>{
unsafe {
let mut array: [_; $usize] = std::mem::MaybeUninit::uninit().assume_init();
for elem in array.iter_mut() {
std::ptr::write(elem, $default);
}
array
}
}
}
用法:
struct S();
let ss: [Option<S>; 1024] = array_init![None; 1024];
1
共 6 条评论, 1 页
评论区
写评论赞,学到了!
--
👇
whfuyn: ```rust fn main() { struct S(); const s: Option = None; let ss: [Option; 1024] = [s; 1024]; }
Playgroud
可以看看1.50.0的更新日志里提到了这个。
1.38里意外允许了这么做,在1.50.0里正式承认这种做法。
测试了一下,错误提示并没有改变,或许是不同case。代码在这里 不知道以后会不会支持这个场景,目前我用这个宏的方式觉得还挺方便的。
👇
songzhi: nightly版里更新了一个提示
nightly版里更新了一个提示
第一个参数由于没有实现copy,所以需要填入一个元素默认的初始化表达式。这个宏主要是为了简化代码,并不能逃避编译器检查。
--
👇
Neutron3529: ``` macro_rules! array_init { ($default:expr; $usize:expr)=>{ unsafe { let mut array: [_; $usize] = std::mem::MaybeUninit::uninit().assume_init(); for elem in array.iter_mut() { std::ptr::write(elem, $default); } array } } } fn main(){ let a=vec![2]; let mut ss=array_init![a;10]; ss[0].push(2); println!("{:?}",ss) }
Compiling playground v0.0.1 (/playground) error[E0382]: use of moved value:
a
--> src/main.rs:14:28 | 13 | let a=vec![2]; | - move occurs becausea
has typeVec<i32>
, which does not implement theCopy
trait 14 | let mut ss=array_init![a;10]; | ^ value moved here, in previous iteration of looperror: aborting due to previous error
For more information about this error, try
rustc --explain E0382
. error: could not compileplayground
To learn more, run the command again with --verbose.
这并不是一个很好的实现。