I find a solution by removing the ~ to Base trait.
The code
//(First and Second think as defined earlier)
enum BaseImpl {
FirstThinkImpl(FirstThink),
SecondThinkImpl(SecondThink),
}
struct Container {
nodeList: Vec<~BaseImpl>,
}
impl<'a> Container {
fn iter_base(&'a self) -> BaseItems<'a> {
let iter = self.nodeList.iter();
BaseItems{ iter : iter }
}
}
struct BaseItems<'a> {
iter : Items<'a, ~BaseImpl>
}
impl<'a> Iterator<&'a Base> for BaseItems<'a> {
fn next(&mut self) -> Option<&'a Base> {
match self.iter.next() {
Some(ref baseimpl) => {
Some(match ***baseimpl{
FirstThinkImpl(ref first) => first as &'a Base,
SecondThinkImpl(ref second)=> second as &'a Base,
})
},
None => None,
}
}
}
Now it compile.
So I try to define a mutable iterator like the immuable and with similar
code I have again the lifetime compile error :
struct BaseMutItems<'a> {
iter : MutItems<'a, ~BaseImpl>
}
impl<'a> Iterator<&'a mut Base> for BaseMutItems<'a> {
fn next(&mut self) -> Option<&'a mut Base> {
match self.iter.next() {
Some(ref mut baseimpl) => {
Some(match ***baseimpl{
FirstThinkImpl(ref mut first) => first as &'a mut Base,
SecondThinkImpl(ref mut second)=> second as &'a mut
Base,
})
},
None => None,
}
}
}
error :
test_enum.rs:125:36: 125:49 error: lifetime of `baseimpl` is too short
to guarantee its contents can be safely reborrowed
test_enum.rs:125 FirstThinkImpl(ref mut first) =>
first as &'a mut Base,
I can't see what's going wrong.
I put all the code if someone want to test :
use std::iter::Iterator;
use std::slice::{Items, MutItems};
trait Base {
fn set_something(&mut self);
fn isSecondThink(&self) -> bool;
}
struct FirstThink{
count1: int,
}
impl Base for FirstThink {
fn set_something(&mut self) {println!("ici First count:{:?}",
self.count1); self.count1+=1;}
fn isSecondThink(&self) -> bool {false}
}
struct SecondThink{
count2: int,
}
impl Base for SecondThink {
fn set_something(&mut self) {println!("ici Second count:{:?}",
self.count2); self.count2+=1;}
fn isSecondThink(&self) -> bool {true}
}
enum BaseImpl {
FirstThinkImpl(FirstThink),
SecondThinkImpl(SecondThink),
}
fn some_second_process(think: &mut SecondThink) {
think.set_something();
}
struct Container {
nodeList: Vec<~BaseImpl>,
}
impl<'a> Container {
fn add_FirstThink(&mut self, think: FirstThink) {
self.nodeList.push(~FirstThinkImpl(think));
}
fn add_SecondThink(&mut self, think: SecondThink) {
self.nodeList.push(~SecondThinkImpl(think));
}
fn iter_base(&'a self) -> BaseItems<'a> {
let iter = self.nodeList.iter();
BaseItems{ iter : iter }
}
fn iter_second(&'a self) -> SecondItems<'a> {
let iter = self.nodeList.iter();
SecondItems{ iter : iter }
}
fn mut_iter_base(&'a mut self) -> BaseMutItems<'a> {
let iter = self.nodeList.mut_iter();
BaseMutItems{ iter : iter }
}
fn appli_secondthink_someprocess(&mut self, fct : fn (&mut
SecondThink)) {
for think in self.nodeList.mut_iter() {
match **think {
FirstThinkImpl(first) => println!(""),
SecondThinkImpl(ref mut second)=> fct(second),
}
}
}
}
struct BaseItems<'a> {
iter : Items<'a, ~BaseImpl>
}
impl<'a> Iterator<&'a Base> for BaseItems<'a> {
fn next(&mut self) -> Option<&'a Base> {
match self.iter.next() {
Some(ref baseimpl) => {
Some(match ***baseimpl{
FirstThinkImpl(ref first) => first as &'a Base,
SecondThinkImpl(ref second)=> second as &'a Base,
})
},
None => None,
}
}
}
struct SecondItems<'a> {
iter : Items<'a, ~BaseImpl>
}
impl<'a> Iterator<&'a SecondThink> for SecondItems<'a> {
fn next(&mut self) -> Option<&'a SecondThink> {
match self.iter.next() {
Some(ref baseimpl) => {
match ***baseimpl{
FirstThinkImpl(ref first) => self.next(),
SecondThinkImpl(ref second)=> Some(second),
}
},
None => None,
}
}
}
struct BaseMutItems<'a> {
iter : MutItems<'a, ~BaseImpl>
}
impl<'a> Iterator<&'a mut Base> for BaseMutItems<'a> {
fn next(&mut self) -> Option<&'a mut Base> {
match self.iter.next() {
Some(ref mut baseimpl) => {
Some(match ***baseimpl{
FirstThinkImpl(ref mut first) => first as &'a mut Base,
SecondThinkImpl(ref mut second)=> second as &'a mut
Base,
})
},
None => None,
}
}
}
#[main]
fn main() {
let first = FirstThink{count1:0};
let second = SecondThink{count2:0};
let mut container = Container{nodeList: Vec::new()};
container.add_FirstThink(first);
container.add_SecondThink(second);
container.appli_secondthink_someprocess(some_second_process);
container.appli_secondthink_someprocess(some_second_process);
for think in container.iter_base() {
println!("ici Second count:{:?}", think.isSecondThink());
}
for think in container.iter_second() {
println!("ici Second count:{:?}", think.isSecondThink());
}
container.appli_secondthink_someprocess(some_second_process);
}
Le 07/04/2014 13:17, Philippe Delrieu a écrit :
I try to implement the iterator like that:
struct BaseItems<'a> {
iter : Items<'a, ~BaseImpl>
}
impl<'a> Iterator<&'a ~Base> for BaseItems<'a> {
fn next(&mut self) -> Option<&'a ~Base> {
match self.iter.next() {
Some(ref baseimpl) => {
Some(&'a match ***baseimpl{
FirstThinkImpl(ref first) => *first as ~Base,
SecondThinkImpl(ref second)=> *second as ~Base,
})
},
None => None,
}
}
}
But I have a lifetime problem. The error is : borrowed value does not
live long enough and reference must be valid for the lifetime &'a as
defined on the block
and :
cannot move out of dereference of `&`-pointer SecondThinkImpl(ref
second)=> *second as ~Base,
Another possibility:
fn next(&mut self) -> Option<&'a ~Base> {
match self.iter.next() {
Some(ref baseimpl) => {
Some(match ***baseimpl{
FirstThinkImpl(ref first) => first as &'a ~Base,
SecondThinkImpl(ref second)=> second as &'a
~Base,
})
},
None => None,
}
}
generate the error: non-scalar cast: `&~FirstThink` as `&'a
~Base<no-bounds>`
I try different possibility but I didn't find how to return a <'a>
lifetime ~Base or Base
I remove the mut to simplify the test of the different lifetime
possibilities.
Philippe
Le 07/04/2014 10:27, Rodrigo Rivas a écrit :
On Sun, Apr 6, 2014 at 7:50 PM, Philippe Delrieu
<[email protected]> wrote:
I need some more help.
The impl Iterator<&mut ~Base> for Container declaration generate
the error:
error: missing lifetime specifier
So I had it but I can't manage to return the next value with the
specified
life time.
The code :
impl<'a> Iterator<&'a mut ~Base> for Container {
/// Advance the iterator and return the next value. Return
`None` when
the end is reached.
fn next(&mut self) -> Option<&'a mut ~Base> {
if self.iter_counter == self.nodeList.len() {
None
} else {
self.iter_counter += 1;
Some(&'a mut match **self.nodeList.get(self.iter_counter){
FirstThinkImpl(first) => first as ~Base,
SecondThinkImpl(second)=> second as ~Base,
})
}
}
}
Generate these errors :
test_enum.rs:58:18: 61:14 error: borrowed value does not live long
enough
test/test_enum.rs:58 Some(&'a mut match
Oh, I think I may have misleaded you... You cannot implement the
iterator directly in Container, because the iterator must handle the
current position, while the Container just holds the values. You need
a intermediate struct that implements the Iterator traits. That's what
the `iter()` and ' move_iter()` functions do for vectors and other
standard containers. So you'll need something along the lines of this
(disclaimer: totally untested!!):
struct Container {
//....
fn iter(&'a self) -> BaseItems<'a> {
let iter = nodeList.iter();
BaseItems{ iter : iter }
}
}
struct BaseItems<'a> {
iter : Items<'a, ~Base>
}
impl<'a> Iterator<&'a mut ~Base> for BaseItems<'a> {
//....
}
BTW, why all the double pointer in all the "&mut ~Base" instead of
just "&mut Base"?
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev