如何在Rust结构中存储闭包?

chhqkbe1  于 2023-04-12  发布在  其他
关注(0)|答案(2)|浏览(149)
struct User {
    id: i8,
    name: &'static str
}

struct UserMethods {
    add_user: Fn(User) -> (),
}

fn main() {
    UserMethods {
        add_user: |user| {

        }
    };
}

编译器说,

error[E0277]: the size for values of type `(dyn Fn(User) + 'static)` cannot be known at compilation time
  --> src/main.rs:11:5
   |
11 | /     UserMethods {
12 | |         add_user: |user| {},
13 | |     };
   | |_____^ doesn't have a size known at compile-time
mnemlml8

mnemlml81#

Fn是一个trait,因此它是无大小的。为了将它存储在结构体或变量中,你必须使用实现Sized的东西,否则编译器无法知道要分配多少内存。
有两种方法可以解决此问题:
1.使用泛型:

struct UserMethods<T: Fn(User)> {
    add_user: T,
}

fn main() {
    UserMethods {
        add_user: |user| {},
    };
}

1.使用Box或任何其他智能指针:

struct UserMethods {
    add_user: Box<dyn Fn(User)>,
}

fn main() {
    UserMethods {
        add_user: Box::new(|user| {}),
    };
}

你也可以使用一个普通的函数指针(感谢@user2722968),但它不如闭包灵活(不能从环境中捕获任何东西):

struct UserMethods {
    add_user: fn(User),
}

fn main() {
    UserMethods {
        add_user: |user| {},
    };
}
lymnna71

lymnna712#

SvetlinZarev's second option只在闭包为'static时有效(它意味着dyn Fn(User) + 'static),如果不是,你必须显式地命名生命周期,类似于这样:

struct UserMethods<'a> {
    add_user: Box<dyn Fn(User) + 'a>,
}

fn main() {
    let a = 99;
    UserMethods {
        add_user: Box::new(|user| { println!("{a}") }),
    };
}

相关问题