如何在Rust结构中存储闭包


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

Fn是一个特性,因此它是不定大小的。为了将其存储在结构或变量中,必须使用实现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| {},
};
}

SvetlinZarev的第二个选项仅在闭包为'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}") }),
};
}

最新更新