When I use a static variable in generic functions, the entities of the variable in each instance of the generic function are all the same.
For instance, in this code
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!
is called just once.
I had checked the assembly code using the Rust playground and saw that the INIT
variable is independent of which type T
actually is although foo<T>
themselves are instantiated with different name.
Is it possible for different instance of the generic function to have different static variables so that println!
is called twice in the above example?
If you find that you need multiple instances of a static variable, this is a strong indication that you should not be using static variables in the first place. Yes, if the same class is loaded in different class loaders, then each copy of the class will have its own statics. However, the only code that can refer statically...
Instance method can access static variables and static methods directly. Static methods can access the static variables and static methods directly. Static methods can’t access instance methods and instance variables directly.
Static methods vs Instance methods in Java. Instance method are methods which require an object of its class to be created before it can be called. To invoke a instance method, we have to create an Object of the class in within which it defined.
member variables. If a class's member variable is static, however, only one instance of the variable exists in memory. All objects of that class have access to that one variable. Static member variables are declared inside the class declaration. Where are static member variables defined? Outside the class declaration.
No. Rust doesn't support having static data tied to a generic parameter.
The closest workaround I can think of would be to use something like the typemap
crate to store one entry per type.
/*!
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");
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With