diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-04-01 10:11:46 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-04-01 14:40:44 -0400 |
| commit | ed63d32651105e56afceb94cbb86f115db235825 (patch) | |
| tree | d1df549a70af147589428d8ade908d1f0560d62f /src/liballoc | |
| parent | d528aa9960cb9b937d8ef6c09905a6a8076d5f3a (diff) | |
| download | rust-ed63d32651105e56afceb94cbb86f115db235825.tar.gz rust-ed63d32651105e56afceb94cbb86f115db235825.zip | |
Add (unstable) FnBox trait as a nicer replacement for `Thunk`. The doc
comment includes a test that also shows how it can be used.
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/boxed.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 550b25ac3a7..8d3a63ceb50 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -355,3 +355,78 @@ impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> { } } } + +/// `FnBox` is a version of the `FnOnce` intended for use with boxed +/// closure objects. The idea is that where one would normally store a +/// `Box<FnOnce()>` in a data structure, you should use +/// `Box<FnBox()>`. The two traits behave essentially the same, except +/// that a `FnBox` closure can only be called if it is boxed. (Note +/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>` +/// closures become directly usable.) +/// +/// ### Example +/// +/// Here is a snippet of code which creates a hashmap full of boxed +/// once closures and then removes them one by one, calling each +/// closure as it is removed. Note that the type of the closures +/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce() +/// -> i32>`. +/// +/// ``` +/// #![feature(core)] +/// +/// use std::boxed::FnBox; +/// use std::collections::HashMap; +/// +/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> { +/// let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new(); +/// map.insert(1, Box::new(|| 22)); +/// map.insert(2, Box::new(|| 44)); +/// map +/// } +/// +/// fn main() { +/// let mut map = make_map(); +/// for i in &[1, 2] { +/// let f = map.remove(&i).unwrap(); +/// assert_eq!(f(), i * 22); +/// } +/// } +/// ``` +#[cfg(not(stage0))] +#[rustc_paren_sugar] +#[unstable(feature = "core", reason = "Newly introduced")] +pub trait FnBox<A> { + type Output; + + extern "rust-call" fn call_box(self: Box<Self>, args: A) -> Self::Output; +} + +#[cfg(not(stage0))] +impl<A,F> FnBox<A> for F + where F: FnOnce<A> +{ + type Output = F::Output; + + extern "rust-call" fn call_box(self: Box<F>, args: A) -> F::Output { + self.call_once(args) + } +} + +#[cfg(not(stage0))] +impl<A,R> FnOnce<A> for Box<FnBox<A,Output=R>> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) + } +} + +#[cfg(not(stage0))] +impl<A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) + } +} |
