提交 09e2ad13 编写于 作者: B bors

auto merge of #19060 : Gankro/rust/super-cloned, r=aturon

Edit: whoops, didn't mean to hit post.

Anyway, this is something I tried to do when I first implemented cloned, but couldn't figure out. Somewhere between then and the PR actually landing, we got Deref of references, so now this works! 🎉 

Also turns out the test for the functionality was never marked as a #[test]. Oops!

Also added a Cloned iterator adaptor. If this isn't desirable, it can be taken out of the PR (seperate commits).
......@@ -65,9 +65,10 @@ trait defined in this module. For loops can be viewed as a syntactical expansion
use cmp::Ord;
use mem;
use num::{ToPrimitive, Int};
use ops::Add;
use ops::{Add, Deref};
use option::{Option, Some, None};
use uint;
#[deprecated = "renamed to Extend"] pub use self::Extend as Extendable;
/// Conversion from an `Iterator`
......@@ -1021,6 +1022,44 @@ pub fn into_option(self) -> Option<(T,T)> {
}
}
/// A trait for iterators that contain cloneable elements
pub trait CloneIteratorExt<A> {
/// Creates an iterator that clones the elements it yields. Useful for converting an
/// Iterator<&T> to an Iterator<T>.
fn cloned(self) -> Cloned<Self>;
}
impl<A: Clone, D: Deref<A>, I: Iterator<D>> CloneIteratorExt<A> for I {
fn cloned(self) -> Cloned<I> {
Cloned { it: self }
}
}
/// An iterator that clones the elements of an underlying iterator
pub struct Cloned<I> {
it: I,
}
impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> {
fn next(&mut self) -> Option<A> {
self.it.next().cloned()
}
fn size_hint(&self) -> (uint, Option<uint>) {
self.it.size_hint()
}
}
impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>>
DoubleEndedIterator<A> for Cloned<I> {
fn next_back(&mut self) -> Option<A> {
self.it.next_back().cloned()
}
}
impl<A: Clone, D: Deref<A>, I: ExactSize<D>> ExactSize<A> for Cloned<I> {}
/// A trait for iterators that are cloneable.
pub trait CloneableIterator {
/// Repeats an iterator endlessly
......
......@@ -153,6 +153,7 @@
use slice;
use slice::AsSlice;
use clone::Clone;
use ops::Deref;
// Note that this is not a lang item per se, but it has a hidden dependency on
// `Iterator`, which is one. The compiler assumes that the `next` method of
......@@ -694,11 +695,12 @@ pub fn take(&mut self) -> Option<T> {
}
}
impl<'a, T: Clone> Option<&'a T> {
/// Maps an Option<&T> to an Option<T> by cloning the contents of the Option<&T>.
impl<'a, T: Clone, D: Deref<T>> Option<D> {
/// Maps an Option<D> to an Option<T> by dereffing and cloning the contents of the Option.
/// Useful for converting an Option<&T> to an Option<T>.
#[unstable = "recently added as part of collections reform"]
pub fn cloned(self) -> Option<T> {
self.map(|t| t.clone())
self.map(|t| t.deref().clone())
}
}
......
......@@ -440,6 +440,23 @@ fn test_rev() {
vec![16, 14, 12, 10, 8, 6]);
}
#[test]
fn test_cloned() {
let xs = [2u8, 4, 6, 8];
let mut it = xs.iter().cloned();
assert_eq!(it.len(), 4);
assert_eq!(it.next(), Some(2));
assert_eq!(it.len(), 3);
assert_eq!(it.next(), Some(4));
assert_eq!(it.len(), 2);
assert_eq!(it.next_back(), Some(8));
assert_eq!(it.len(), 1);
assert_eq!(it.next_back(), Some(6));
assert_eq!(it.len(), 0);
assert_eq!(it.next_back(), None);
}
#[test]
fn test_double_ended_map() {
let xs = [1i, 2, 3, 4, 5, 6];
......
......@@ -241,14 +241,29 @@ fn test_collect() {
assert!(v == None);
}
#[test]
fn test_cloned() {
let s = 1u32;
let n: Option<&'static u32> = None;
let o = Some(&s);
assert_eq!(o.clone(), Some(&s));
assert_eq!(o.cloned(), Some(1u32));
assert_eq!(n.clone(), None);
assert_eq!(n.cloned(), None);
let val1 = 1u32;
let mut val2 = 2u32;
let val1_ref = &val1;
let opt_none: Option<&'static u32> = None;
let opt_ref = Some(&val1);
let opt_ref_ref = Some(&val1_ref);
let opt_mut_ref = Some(&mut val2);
// None works
assert_eq!(opt_none.clone(), None);
assert_eq!(opt_none.cloned(), None);
// Mutable refs work
assert_eq!(opt_mut_ref.cloned(), Some(2u32));
// Immutable ref works
assert_eq!(opt_ref.clone(), Some(&val1));
assert_eq!(opt_ref.cloned(), Some(1u32));
// Double Immutable ref works
assert_eq!(opt_ref_ref.clone(), Some(&val1_ref));
assert_eq!(opt_ref_ref.clone().cloned(), Some(&val1));
assert_eq!(opt_ref_ref.cloned().cloned(), Some(1u32));
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册