2015-10-31 2 views
6

私は、関数ポインタであるフィールドを持つ構造体を持っています。私はその構造体のClone形質を実装したいが、彼らは、少なくとも一つのパラメータがあれば、私は、関数ポインタは、クローン化することができないことはできませんので:関数ポインタをクローンする方法

fn my_fn(s: &str) { 
    println!("in my_fn {}", s); 
} 

type TypeFn = fn(s: &str); 

#[derive(Clone)] 
struct MyStruct { 
    field: TypeFn 
} 

fn main() { 
    let my_var = MyStruct{field: my_fn}; 
    let _ = my_var.clone(); 
} 

Link to playgroundを。

答えて

3

問題は、関数ポインタは一般的にはクローン可能ではありませんが、実際には&strの生存期間にわたって一般的な関数を持っているということです。たとえば、i32にはライフタイムがないため、&stri32に置き換えるとコードがコンパイルされます。あなたの状況では、明示的な関数ポインタに寿命を行う必要があります。

type TypeFn<'a> = fn(s: &'a str); 

これは明らかに、あまりにも、構造体にバブルアップ:

#[derive(Clone)] 
struct MyStruct<'a> { 
    field: TypeFn<'a> 
} 

これは、次のコードの種類を防ぎます

let my_var = MyStruct{field: my_fn}; 
let s = String::new(); 
(my_var.field)(&s); 

実際、問題はバグだということです。 @MattBrubeck 's answerのように、関数ポインタはCopyを実装しています。だから、あなただけの関数ポインタのCopyのimplを使用して、手動でCloneを実装することができます。その種類内の参照と

impl Clone for MyStruct { 
    fn clone(&self) -> Self { 
     MyStruct { 
      field: self.field, 
     } 
    } 
} 
+0

正解はバグです...自分の投稿をdownvoteすることはできません^^私は受け入れられた答えを削除できません... –

+0

私はhttpで提案された方法を使用しました://meta.stackoverflow.com/a/266154/1103681しかし、受け入れられた答えを変更してコメントを残してください。それから私は私の答えを削除します。 –

8

関数ポインタをCloneためissue #24000のを実装していません。つまり、それらを含む型の場合は#[derive(Clone)]できません。手動で実装する必要があります。

しかし、機能ポインタCopyあるので、あなたはあなたのタイプのためのimpl Copy、その後はそれに手動でimpl Clone使用することができます。

impl Copy for MyStruct {} 

impl Clone for MyStruct { 
    fn clone(&self) -> Self { *self } 
} 

Playpen link

関連する問題