< 返回版块

henrylee2cn 发表于 2021-02-27 23:36

Tags:array,macro_rules

问题代码:

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];

评论区

写评论
作者 henrylee2cn 2021-02-28 15:21

赞,学到了!

--
👇
whfuyn: ```rust fn main() { struct S(); const s: Option = None; let ss: [Option; 1024] = [s; 1024]; }


[Playgroud](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=04758115ff6d53fc3e26b40850352e3a)

可以看看1.50.0的[更新日志](https://blog.rust-lang.org/2021/02/11/Rust-1.50.0.html#const-value-repetition-for-arrays)里提到了这个。

1.38里意外允许了这么做,在1.50.0里正式承认这种做法。
whfuyn 2021-02-28 14:44
fn main() {
    struct S();
    const s: Option<S> = None;
    let ss: [Option<S>; 1024] = [s; 1024];
}

Playgroud

可以看看1.50.0的更新日志里提到了这个。

1.38里意外允许了这么做,在1.50.0里正式承认这种做法。

作者 henrylee2cn 2021-02-28 14:23

测试了一下,错误提示并没有改变,或许是不同case。代码在这里 不知道以后会不会支持这个场景,目前我用这个宏的方式觉得还挺方便的。

👇
songzhi: nightly版里更新了一个提示

作者 henrylee2cn 2021-02-28 10:06

第一个参数由于没有实现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 because a has type Vec<i32>, which does not implement the Copy trait 14 | let mut ss=array_init![a;10]; | ^ value moved here, in previous iteration of loop

error: aborting due to previous error

For more information about this error, try rustc --explain E0382. error: could not compile playground

To learn more, run the command again with --verbose.

这并不是一个很好的实现。
Neutron3529 2021-02-28 03:19
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 because `a` has type `Vec<i32>`, which does not implement the `Copy` trait
14 |     let mut ss=array_init![a;10];
   |                            ^ value moved here, in previous iteration of loop

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

这并不是一个很好的实现。

1 共 6 条评论, 1 页