struct New {num: i32 }
struct ComplexThing <A> //( L1)
{
calls: Box<FnMut(&A)+Send+Sync>,
}
trait newstrait {
fn display(&self);
}
impl newstrait for New {
fn display(&self){println!("new's num value : {}",self.num);}
}
impl newstrait for i32{
fn display(&self){println!("number : {}",self);}
}
fn printline<A:newstrait>(p: &A){
p.display();
}
fn main(){
let mut vec = Arc::new(Mutex::new(vec![ComplexThing{calls: Box::new(printline)}]));
let mut len;
{
let mut vec = vec.lock().unwrap();
vec.push(ComplexThing{calls: Box::new(printline)}); //storing function in vector
len = vec.len();
}
for i in 0..len{
thread::spawn(move||{
let vec = vec.clone();
let mut vec= vec.lock().unwrap();
let ref mut elem =vec[i].calls;
if i!=1{
elem(&New{num:1080}); //calling stored function with instance of structure New as argument ( L2 )
}else{
let num = 434;
elem(&num); //calling stored function with i32 as an argument (L3)
}
});
}
}
It is initialising generic type (A) at L1 with the type of arguments which are sent first and giving error on L3
function_structure2.rs:33:11: 33:15 error: mismatched types:
expected &new,
found &_
(expected struct new,
found integral variable) [E0308]
function_structure2.rs:33 elem(&num);
I read from (https://gist.github.com/Kimundi/8391398) that rust makes copies of function which takes generic arguments for each type at compile time .
If a generic type is initialised with with the type of arguments which are sent first ,then how to overcome this???
<anon>:28:33: 28:45 error: wrong number of type arguments: expected 1, found 0 [E0243]
<anon>:28 let mut vec : Arc<Mutex<Vec<ComplexThing>>> = Arc::new(Mutex::new(vec![ComplexThing { calls: Box::new(printline) }]));
Which hints at what is going on. Without the declaration the compiler is seeing the first call to ComplexThing and saying "Oh A is of type struct New" so when you try calling it with an i32, it starts complaining.
Unfortunately I don't know how to move forward from that, when I do:
I got it working but I'm not sure if the results are going to work for you...
use std::sync::{Arc, Mutex};
use std::thread;
struct New {
num: i32,
}
struct ComplexThing {
calls: Box<FnMut(&newstrait) + Send + Sync>,
}
trait newstrait {
fn display(&self);
}
impl newstrait for New {
fn display(&self) {
println!("new's num value : {}", self.num);
}
}
impl newstrait for i32 {
fn display(&self) {
println!("number : {}", self);
}
}
fn printline(p: &newstrait) {
p.display();
}
fn main() {
let mut vec : Arc<Mutex<Vec<ComplexThing>>> = Arc::new(Mutex::new(vec![ComplexThing { calls: Box::new(printline) }]));
let mut len;
{
let mut vec = vec.lock().unwrap();
vec.push(ComplexThing { calls: Box::new(printline) }); //storing function in vector
len = vec.len();
}
for i in 0..len {
let vec = vec.clone();
thread::spawn(move || {
let mut vec = vec.lock().unwrap();
let ref mut elem = vec[i].calls;
if i != 1 {
let num : i32 = 434;
elem(&num); //calling stored function with i32 as an argument (L3)
}
else {
elem(&New { num: 1080 }); //calling stored function with instance of structure New as argument ( L2 )
}
});
}
}
I had to change ComplexThing::calls so that it took a &newstrait instead of a generic so it could be properly sized, I guess with the generic it couldn't guarantee the size of the structure.
I also had to change the signature of printline to take a &newstrait, otherwise the compiler couldn't guarantee it's lifetime. I suspect it because when printline uses a generic there end up being multiple implementations of the function, one for each data type passed in. By changing it to take the trait there ends up only 1 implementation...