2017-08-26 50 views
9

Gdy używam zmiennej statycznej w funkcjach ogólnych, elementy zmiennej w każdym wystąpieniu funkcji ogólnej są takie same.Czy różne instancje funkcji ogólnej mogą mieć różne zmienne statyczne?

Na przykład, w tym kodzie

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! nazywa się tylko raz.

Sprawdziłem kod zestawu przy użyciu placu zabaw Rust i zauważyłem, że zmienna INIT jest niezależna od typu T tak naprawdę, chociaż foo<T> same są tworzone z inną nazwą.

Czy jest możliwe, aby różne wystąpienie funkcji ogólnej miało różne zmienne statyczne, aby println! było wywoływane dwukrotnie w powyższym przykładzie?

Odpowiedz

6

Nie. Rust nie obsługuje statycznych danych związanych z ogólnym parametrem.

Najbliższym sposobem obejścia tego problemu byłoby użycie czegoś takiego jak skrzynia typemap do przechowywania jednego wpisu dla każdego typu.

/*! 
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"); 
    }); 
} 
+0

Chociaż może to nie być dobre pytanie, czy wiesz, dlaczego rdza nie obsługuje statycznej zmiennej o parametrze ogólnym? – hfukuda

+1

@hfukuda: Niezupełnie. Prawdopodobnie dlatego, że nikt nigdy nie potrzebował tego wystarczająco źle. –