当我在泛型函数中使用静态变量时,泛型函数的每个实例中的变量实体都是相同的.

例如,在这个代码中

fn foo<T>() {
    use std::sync::{Once, ONCE_INIT};

    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        // run initialization here
        println!("Called");
    });
}

fn main() {
    foo::<i64>();
    foo::<i64>();
    foo::<isize>();
}

println!只叫一次.

我使用Rust Playway判断了汇编代码,发现INIT变量与T实际是哪种类型无关,尽管foo<T>本身是用不同的名称实例化的.

在上面的例子中,有两次调用不同的通用变量吗?

推荐答案

不支持.Rust不支持将静态数据绑定到通用参数.

我能想到的最接近的解决方法是使用typemap crate 之类的东西来存储每种类型的条目.

/*!
Add to `Cargo.toml`:

```cargo
[dependencies]
lazy_static = "0.2.8"
typemap = "0.3.3"
```
*/
#[macro_use] extern crate lazy_static;
extern crate typemap;

fn main() {
    foo::<i64>();
    foo::<i64>();
    foo::<isize>();
}

fn foo<T: 'static>() {
    use std::marker::PhantomData;
    use std::sync::Mutex;
    use typemap::{ShareMap, TypeMap};

    // Use `fn(T)` as it avoids having to require that `T` implement
    // `Send + Sync`.
    struct Key<T>(PhantomData<fn(T)>);

    impl<T: 'static> typemap::Key for Key<T> {
        type Value = ();
    }

    lazy_static! {
        static ref INIT: Mutex<ShareMap> = Mutex::new(TypeMap::custom());
    }

    INIT.lock().unwrap().entry::<Key<T>>().or_insert_with(|| {
        println!("Called");
    });
}

Rust相关问答推荐

MacOS(AARCH64)上Ghidra中的二进制补丁导致进程终止

如何格式化传入Rust中mysql crate的Pool::new的字符串

有没有办法避免在While循环中多次borrow `*分支`

将数组转换为HashMap的更简单方法

如何点击()迭代器?

为什么基于高山Linux的Docker镜像不能在绝对路径下找到要执行的命令?

如何向下转换到MyStruct并访问Arc Mutex MyStruct实现的方法?

Rust中WPARAM和VIRTUAL_KEY的比较

将特征与具有生命周期的关联类型一起使用时的生命周期方差问题

.在 Rust 模块标识符中

tokio::sync::broadcast::Receiver 不是克隆

使用 Option 来分配?

通过mem::transmute将数组展平安全吗?

没有明确地说return会产生错误:match arms have incompatible types

max(ctz(x), ctz(y)) 有更快的算法吗?

如何在 Rust 中将 UTF-8 十六进制值转换为 char?

试图理解 Rust 中的可变闭包

如何在 Rust 中返回通用 struct

从函数返回 u32 的数组/切片

这个 match 语句的默认值应该是什么,还有一种方法可以解开 Some case (chess in rust)