1樓:hjiayz
加上refcell就行了,如果多執行緒需要上鎖Rust Playground
usestd::cell::RefCell;pub
struct
CallBack
<'a,
T,F>
pubstruct
Context
<'a,
T,F>
impl
<'a,
T: Copy
+Default
,F: Fn(T
)>CallBack
<'a,
T,F>
}impl
<'a,
T: Copy
+Default
,F: Fn(T
)>Context
<'a,
T,F>
}pub
fnget_value(&
self
)-> T
pubfn
set_value(&
'aself
,new_value: T)}
pubfn
add_callback(&
'aself
,callback: F))
}}#[cfg(test)]
modtests",
value
));context
.set_value(5
);assert_eq!(
5,context
.get_value
());}}
2樓:傳統的幻想書屋
你最好換個設計,互相引用是能避免就盡量避免的,就算你的context要擁有callback,但是可以讓callback不引用context,而是給notify加個引數,把context引用傳進去,這樣至少不會要callback物件本身持有context引用。否則互相擁引用對方會導致你兩個引用都是不可變的之後,無法可變借用其中任何乙個,那你的add和set就做不了了。
然後就是,你這個設計本身就很有問題,首先你的引數是乙個Fn(T)->()型別,這實際上代表乙個可呼叫物件,或者有捕獲的閉包,而不僅僅是乙個函式指標,你這樣寫,傳的閉包沒有捕獲變數還好,編譯器會自動看作函式指標,但是一旦要捕獲變數就不行了,因為閉包不是固定大小的。
然後,既然取消了相互引用,那麼這個生命週期也是不必要寫的了,幫你整體改了一下。
pubstruct
CallBack
Context
+Default >CallBack new( f: Box )-> () >)-> Self}} impl +Default >Context fnget_value(& self )-> T pubfn set_value(& mutself ,new_value: T)} pubfn add_callback(& mutself ,callback: Box )-> () >)}fnadd_callback()" ,value ))); context .add_callback (Box::new(| value |println!( "second callback:value changed to {}" ,value ))); context .add_callback (Box::new(| value |println!( "third callback:value changed to {}" ,value ))); context .set_value(5 );assert_eq!( 5,context .get_value ());}fn main ()這是執行結果 first callback:value changed to 5 second callback:value changed to 5 third callback:value changed to 5 然後就是用函式指標,感覺更符合你的需求 pub struct StaticCallBack pub struct StaticContext impl StaticCallBack ", value)); context.add_callback(|value| println!("second callback:value changed to {}", value)); context.add_callback(|valueprintln!("third callback: value changed to {}", value不能捕獲變數context.add_callback(other_func); context.set_value(5); assert_eq!(5, context.get_value()); }fn main() 執行結果跟上面一樣,就不放了。 所以是你自己搞複雜了,要實現這個功能沒那麼複雜。。。。。。 更新,如果Context只是持有閉包的引用而不是所有權,那麼應該用&dyn Fn(T)->()型別,並指明生命週期引數。 pubstruct CallBack <'a, T>pubstruct Context <'a, T>impl <'a, T: Copy +Default >CallBack <'a, T>pubfn new( f: & 'adynFn( T)->()) -> Self}} impl <'a, T: Copy +Default >Context <'a, T>}pub fnget_value(& self )-> T pubfn set_value(& mutself ,new_value: T)} pubfn add_callback(& mutself ,callback: & 'adynFn( T))}fn add_callback (num: i32)" ,value );println!( "capture outer value:{}" ,num );//捕獲num };let call_back2 =|value|" ,value );println!( "capture outer value:{}" ,num );}; letcall_back3 =|value|" ,value );println!( "capture outer value:{}" ,num );}; //需要繫結乙個名稱,保證閉包比context活得長。 letmut context =Context::new ();context .add_callback(& call_back1 );//傳引用(可變引用也是可以的) context .add_callback(& call_back2 );context .add_callback(& call_back3 );context .set_value(5 );assert_eq!( 5,context .get_value ());}fn main ()用引用的話應該是不需要分配堆記憶體的,因為用引用保證了閉包比你的context活得長,就直接存個胖指標指向棧上的閉包就行了,不需要存在堆裡,但是你如果你的context要持有閉包,那引數如果是引用就只能clone乙個了。 最後是閉包的可變引用,也就是傳進來的是FnMut,那你就把裡面都改成可變就行了。 pubstruct CallBack <'a, T>pubstruct Context <'a, T>impl <'a, T: Copy +Default >CallBack <'a, T>pubfn new( f: & 'amut dynFnMut(T )->()) -> Self}} impl <'a, T: Copy +Default >Context <'a, T>}pub fnget_value(& self )-> T pubfn set_value(& mutself ,new_value: T)} pubfn add_callback(& mutself ,callback: & 'amut dynFnMut(T ))}fnadd_callback (num1:& muti32 ,num2:& muti32 ,num3:& muti32)" ,value);* num1+=1 ;println!( "capture outer value:{}" ,num1 );}; letmut call_back2 =|value|" ,value);* num2+=1 ;println!( "capture outer value:{}" ,num2 );}; letmut call_back3 =|value|" ,value);* num3+=1 ;println!( "capture outer value:{}" ,num3 );}; letmut context =Context::new ();context .add_callback(& mutcall_back1 );context .add_callback(& mutcall_back2 );context .add_callback(& mutcall_back3 );context .set_value(5 );assert_eq!( 5,context .get_value ());}fn main ()測試結果 first callback:value changed to 5 capture outer value:51 second callback:value changed to 5 capture outer value:101 third callback:value changed to 5 capture outer value:151 反正意思就是這麼個意思,設計方案也挺多的,要改建議先改設計方案,而不是先去搞一些跟rust所有權系統作對的設計。 判斷struct unbinding,用這個方法本來就不行。換gcc clang的 擴充套件,把unbinding的stmt轉為expr,在判斷expr合法性即可。 不是很明白,序列化和反序列化的意思,如果你是要計算成員數量的話 包括陣列內 include include include inclu... Noir 比如某人70kg體重,體脂很高,那麼他的三大項成績也要以70的多少倍為標準嗎?是的,沒人管你體脂多少,上比賽規定的稱,稱完多重就是多重 2.問題是脂肪不產生力量,他和低體脂的70kg比起來是不是很大劣勢? 卞策 包含。確實存在劣勢。按你這麼說,確實高體脂的乙在這個體重的肌肉表現更好,因為他... 暮無井見鈴 include intmain foo std cout foo n p this endl return0 可以用捕獲 this 的藍陀表示式再帶上 替換最後乙個非靜態成員的預設初始化器。但其他特殊成員函式似乎沒法手動定製 胖財 顯然沒有名字的類是沒法顯式寫構造的,但是我們有C 11的...在 C 17 中包含陣列的聚合型別如何獲取成員個數
力量舉中的體重級別包含體脂很高的人嗎?
在 C 11 中,如何為匿名的結構體新增建構函式?