【问题标题】:How do I construct static variables with a for loop and store them in a static array?如何使用 for 循环构造静态变量并将它们存储在静态数组中?
【发布时间】:2020-06-15 14:16:04
【问题描述】:

我需要静态变量(或与模块/文件关联的任何变量)和一个静态数组来将它们保存在同一个模块中。它们没有必要指向相同的内存。静态变量需要一个循环来初始化。这在 Rust 中可行吗?

在代码中,如下所示。

use std::collections::HashSet;

pub struct A {
    char_lens: HashSet<u8>,
}

impl A {
    pub(crate) fn new(s: &'static str) -> A {
        let mut char_lens: HashSet<u8> = HashSet::new();
        for s in s.split_whitespace() {
            char_lens.insert(s.len() as u8);
        }
        A { char_lens }
    }
}

static VAR_A1: A = A::new("some string 1");
static VAR_A2: A = A::new("some string 2");

static A_ARRAY: [A; 2] = [VAR_A1, VAR_A2];

playground

上面的代码失败了,因为静态变量不能使用循环来初始化自己:

error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
  --> src/lib.rs:17:20
   |
17 | static VAR_A1: A = A::new("some string 1");
   |                    ^^^^^^^^^^^^^^^^^^^^^^^

我尝试使用 lazy_static 板条箱:

use lazy_static::lazy_static; // 1.4.0
use std::collections::HashSet;

pub struct A {
    char_lens: HashSet<u8>,
}

impl A {
    pub(crate) fn new(s: &'static str) -> A {
        let mut char_lens: HashSet<u8> = HashSet::new();
        for s in s.split_whitespace() {
            char_lens.insert(s.len() as u8);
        }
        A { char_lens }
    }
}

lazy_static! {
    static ref VAR_A1: A = A::new("some string 1");
    static ref VAR_A2: A = A::new("some string 2");
    static ref A_ARRAY: [A; 2] = [VAR_A1, VAR_A2];
}

playground

这现在失败了,因为lazy_static 在后台为静态变量生成了一个唯一的结构。现在VAR_A1VAR_A2 有不同的类型,没有办法引用数组的类型。

error[E0308]: mismatched types
  --> src/lib.rs:21:35
   |
21 |     static ref A_ARRAY: [A; 2] = [VAR_A1, VAR_A2];
   |                                   ^^^^^^ expected struct `A`, found struct `VAR_A1`

【问题讨论】:

  • 您是否需要 A1A2 作为单独的变量?
  • @Shepmaster 需要是什么意思?它们代表两个不同的东西。
  • 我的意思是:包含值的数组是否可以接受,而不定义A1 / A2
  • @Shepmaster 我需要变量和包含变量的数组。它们没有必要指向同一个内存。
  • 您当前的代码无法工作,因为[VAR_A1, VAR_A2] 会将VAR_A1 的所有权从其变量转移到数组中,从而使变量处于未定义状态。跨度>

标签: rust


【解决方案1】:

如果您对引用没问题,只需引用并使用 deref coercion:

static ref A_ARRAY: [&'static A; 2] = [&VAR_A1, &VAR_A2];

游乐场:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bee75c90fef228898a737ae08aa89528


如果你需要一个拥有的值,你可以使用.clone()

#[derive(Clone)] // For this method, we need to be able to clone.
pub struct A {
    char_lens: HashSet<u8>,
}

// ...

static ref A_ARRAY: [A; 2] = [VAR_A1.clone(), VAR_A2.clone()];

游乐场:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3d48026b379e1fc3412d3f0af52286e4

【讨论】:

  • 哦,我明白了,std::ops::Dereflazy_static! 宏的范围内。很有趣。
猜你喜欢
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
相关资源
最近更新 更多