당신은 당신의 자신의 반복자를 구현하거나, (하나 개의 작은 unsafe
블록)이 같은 Chars
을 포장 수 :
// deriving Clone would be buggy. With Rc<>/Arc<> instead of Box<> it would work though.
struct OwnedChars {
// struct fields are dropped in order they are declared,
// see https://stackoverflow.com/a/41056727/1478356
// with `Chars` it probably doesn't matter, but for good style `inner`
// should be dropped before `storage`.
// 'static lifetime must not "escape" lifetime of the struct
inner: ::std::str::Chars<'static>,
// we need to box anyway to be sure the inner reference doesn't move when
// moving the storage, so we can erase the type as well.
// struct OwnedChar<S: AsRef<str>> { ..., storage: Box<S> } should work too
storage: Box<AsRef<str>>,
}
impl OwnedChars {
pub fn new<S: AsRef<str>+'static>(s: S) -> Self {
let storage = Box::new(s) as Box<AsRef<str>>;
let raw_ptr : *const str = storage.as_ref().as_ref();
let ptr : &'static str = unsafe { &*raw_ptr };
OwnedChars{
storage: storage,
inner: ptr.chars(),
}
}
pub fn as_str(&self) -> &str {
self.inner.as_str()
}
}
impl Iterator for OwnedChars {
// just `char` of course
type Item = <::std::str::Chars<'static> as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
impl DoubleEndedIterator for OwnedChars {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
impl Clone for OwnedChars {
fn clone(&self) -> Self {
// need a new allocation anyway, so simply go for String, and just
// clone the remaining string
OwnedChars::new(String::from(self.inner.as_str()))
}
}
impl ::std::fmt::Debug for OwnedChars {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let storage : &str = self.storage.as_ref().as_ref();
f.debug_struct("OwnedChars")
.field("storage", &storage)
.field("inner", &self.inner)
.finish()
}
}
// easy access
trait StringExt {
fn owned_chars(self) -> OwnedChars;
}
impl<S: AsRef<str>+'static> StringExt for S {
fn owned_chars(self) -> OwnedChars {
OwnedChars::new(self)
}
}
이 playground
을 [ 같은 것] (https://play.rust-lang.org/?gist=8a5cc326c0fa08cafe7733251ac53546&version=stable), [대여 상자] (https : // 상자 .io/상자/대여). 불행히도 놀이터에서는 작동하지 않습니다. – red75prime
왜 여분 상자가 필요한가요? 'S'는 오직'String','Box'또는 다른 종류의'str' 참조 만 가질 수 있습니다, 맞습니까? 따라서 저장소는 할당 된 힙이어야하며 ('정적'이 아닌 경우) 'S'가 삭제 될 때까지 이동하지 않습니다. (OwnedChars가 물건을 '밀어 넣거나'움직이지 않는 한) –
trentcl
작은 문자열 최적화로 문자열 저장 유형을 만들 수 있습니다 (['smallvec'] (https://crates.io 참조)./crates/smallvec) 만들기). – Stefan