2017-02-23 14 views
0

私はC++ std::bindと似たようなことをして、別の関数の引数としてバインドされた関数ポインタを渡したいと思います。構造体インスタンスの関数ポインタを関数の引数(C++のstd :: bindのようなもの)

以下のコードは失敗した試行を示し、私が何をしようとしているかを示しています。

pub struct MyStruct { 
    x: i64 
} 

impl MyStruct { 
    pub fn struct_function(&mut self, val: i64) { 
     self.x += val; 
    } 
} 

fn normal_function(val: i64) { 
    println!("sum -> {}", val + 1); 
} 

fn do_something_with_a_function(f: fn(i64)) { 
    f(23); 
} 

fn main() { 
    // This works as you'd expect 
    do_something_with_a_function(normal_function as fn(i64)); 

    // What I'd like to do 
    // This attempts to use a closure, but throws an error. 
    let instance = MyStruct{x: 0}; 
    let instance_function = |val: i64|{instance.struct_function(val)}; 
    do_something_with_a_function(instance_function as fn(i64)); 
} 

エラー:

error: non-scalar cast: [[email protected]/main.rs:25:29: 25:72 instance:&mut MyStruct] as fn(i64)

答えて

3

これはいくつかのコードに単にポインタである関数ポインタfn(i64)、の間の差についてであり、そしていくつかのデータを有する非nameable構造体であり、閉鎖、 (コンテキスト)と呼出し方法。

はクロージャを渡すには、呼び出し可能なタイプに機能を汎用的にする必要があります。

fn do_something_with_a_function<F: FnMut(i64)>(mut f: F) { 
    f(23); 
} 

これはFnMut(i64)を実装タイプのものを取ることができることを言います。 FnMutは、呼び出されたときにそのコンテキストへの変更可能な参照を取得することを意味します(この場合は、FnまたはFnOnceを使用する可能性があります; the book chapter on closuresを参照)。通常の関数もこれらの特性を実装します。 FnMutと同じ理由で、fmutでなければなりません。 instance_functionは今可変であることを

fn main() { 
    do_something_with_a_function(normal_function); 

    let mut instance = MyStruct{x: 0}; 
    let mut instance_function = |val: i64|{instance.struct_function(val)}; 
    do_something_with_a_function(&mut instance_function); 
    do_something_with_a_function(&mut instance_function); 
} 

注意とdo_something_with_a_function()に渡さ&mut参照:

はここで更新され、発信者です。それが価値によって渡されれば(それは一度動く)、それは動かされるので、あなたは再びそれを使うことができません。

Playground

関連する問題