通用的特性,适用于所有实现iter()的容器。

huangapple go评论58阅读模式
英文:

Generic trait for all containers implementing iter()

问题

抱歉,您提供的代码有一些问题,需要做一些更改才能使其正常工作。以下是修复后的代码:

trait Monotonic<'a, T: 'a + ?Sized> {
    fn is_monotonic(&mut self) -> bool {
        return true;
    }
}

impl<'a, T: 'a + ?Sized, C> Monotonic<'a, T> for C
where C: IntoIterator<Item=&'a T> + ?Sized {}


fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
        print!("Is monotonic!");
    }
}

您的问题是关于类型边界和生命周期的问题。在 IntoIterator 的实现中,Item 的生命周期应该与 trait 的生命周期 'a 一致。此外,您的 print! 宏应该使用单引号 ' 而不是双引号 "

经过这些更改,您的代码应该能够正常工作。这个修复解决了编译器报告的问题。希望这有所帮助!

英文:

I'm trying to implement a trait for all containers that implement iter(), ie. for all containers that provide an IntoIterator&lt;Item=&amp;&#39;a T&gt;. I've tried this, but unfortunately, even for the simplest case it is failing. Maybe someone knows what I'm doing wrong?

trait Monotonic&lt;&#39;a, T: &#39;a + ?Sized&gt; {
    fn is_monotonic(&amp;mut self) -&gt; bool {
	return true;
    }
}

impl&lt;&#39;a, T: &#39;a + ?Sized, C&gt; Monotonic&lt;&#39;a, T&gt; for C
where C: IntoIterator&lt;Item=&amp;&#39;a T&gt; + ?Sized {}


fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
	print!(&quot;Is monotonic!&quot;);
    }
}

The compiler complains about not satisfied bounds:

error[E0599]: the method `is_monotonic` exists for struct `Vec&lt;u32&gt;`, but its trait bounds were not satisfied
  --&gt; src/test.rs:13:10
   |
13 |     if v.is_monotonic() {
   |          ^^^^^^^^^^^^ method cannot be called on `Vec&lt;u32&gt;` due to unsatisfied trait bounds
  --&gt; /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/alloc/src/vec/mod.rs:400:1
   |
   |   = note: doesn&#39;t satisfy `&lt;Vec&lt;u32&gt; as IntoIterator&gt;::Item = &amp;_`
  
 = note: doesn&#39;t satisfy `Vec&lt;u32&gt;: Monotonic&lt;&#39;_, _&gt;`
   |
note: trait bound `[u32]: IntoIterator` was not satisfied
  --&gt; src/test.rs:8:10
   |
7  | impl&lt;&#39;a, T: &#39;a + ?Sized, C&gt; Monotonic&lt;&#39;a, T&gt; for C
   |                             ----------------     -
8  | where C: IntoIterator&lt;Item=&amp;&#39;a T&gt; + ?Sized {}
   |          ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
      `&lt;Vec&lt;u32&gt; as IntoIterator&gt;::Item = &amp;_`
      `&lt;[u32] as IntoIterator&gt;::Item = &amp;_`
  --&gt; src/test.rs:8:23
   |
7  | impl&lt;&#39;a, T: &#39;a + ?Sized, C&gt; Monotonic&lt;&#39;a, T&gt; for C
   |                             ----------------     -
8  | where C: IntoIterator&lt;Item=&amp;&#39;a T&gt; + ?Sized {}
   |                       ^^^^^^^^^^ unsatisfied trait bound introduced here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.

I've already tried to solve this on my own, but after several attempts I'm at a point where some help would be highly appreciated!

答案1

得分: 2

根据其文档Vec&lt;T&gt; 实现以下 IntoIterator 特质:

  • IntoIterator&lt;Item = &amp;&#39;a T&gt; for &amp;&#39;a Vec&lt;T, A&gt;
  • IntoIterator&lt;Item = &amp;&#39;a mut T&gt; for &amp;&#39;a mut Vec&lt;T, A&gt;
  • IntoIterator&lt;Item = T&gt; for Vec&lt;T, A&gt;

你正在调用它的变量 v 是一个 Vec&lt;u32&gt;,它只实现了 IntoIterator&lt;Item = u32&gt;,而不是任何与你的特质需要的 &amp;&#39;a u32 相关的内容。

有几种解决方法。第一种是在 &amp;v 上运行代码:

trait Monotonic&lt;&#39;a, T: &#39;a + ?Sized&gt; {
    fn is_monotonic(&amp;mut self) -&gt; bool {
        return true;
    }
}

impl&lt;&#39;a, T: &#39;a + ?Sized, C&gt; Monotonic&lt;&#39;a, T&gt; for C where C: IntoIterator&lt;Item = &amp;&#39;a T&gt; + ?Sized {}

fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if (&amp;v).is_monotonic() {
        print!(&quot;Is monotonic!&quot;);
    }
}

尽管这可能不是你想要的,因为我从你的问题中了解到你想要你的 Monotonic 特质尽可能通用地实现。为此,只需删除 &amp; 要求:

trait Monotonic&lt;&#39;a, T: &#39;a + ?Sized&gt; {
    fn is_monotonic(&amp;mut self) -&gt; bool {
        return true;
    }
}

impl&lt;&#39;a, T: &#39;a + ?Sized, C&gt; Monotonic&lt;&#39;a, T&gt; for C where C: IntoIterator&lt;Item = T&gt; + ?Sized {}

fn main() {
    let mut v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
        print!(&quot;Is monotonic!&quot;);
    }
}

关于你当前的代码结构,有几点需要注意:

  • 尽管这在技术上可以编译,但将无法实现你的函数。IntoIterator 消耗 你调用它的对象,但你的 is_monotonic 函数只能对其进行 &amp;mut 访问,所以你将无法在这里调用 into_iter

    你可能希望的是让 is_monotonic 消耗 这个值,然后仅为 &amp;T 实现它。

  • 你的 Monotonic 函数不需要任何泛型参数,因此请将它们删除。

trait Monotonic {
    fn is_monotonic(self) -&gt; bool;
}

impl&lt;&#39;a, T, C&gt; Monotonic for &amp;&#39;a C
where
    &amp;&#39;a C: IntoIterator&lt;Item = T&gt;,
{
    fn is_monotonic(self) -&gt; bool {
        let mut iter = self.into_iter();

        // 对迭代器进行某些操作
        let x = iter.next().unwrap();

        // 返回结果
        true
    }
}

fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
        print!(&quot;Is monotonic!&quot;);
    }
}

这是一个假设 is_monotonic 是指单调递增的示例实现:

trait Monotonic {
    fn is_monotonic(self) -&gt; bool;
}

impl&lt;&#39;a, T, C&gt; Monotonic for &amp;&#39;a C
where
    &amp;&#39;a C: IntoIterator&lt;Item = T&gt;,
    T: PartialOrd,
{
    fn is_monotonic(self) -&gt; bool {
        let mut iter = self.into_iter();

        if let Some(first) = iter.next() {
            let mut previous = first;
            for next in iter {
                if !next.ge(&amp;previous) {
                    return false;
                }
                previous = next;
            }
            true
        } else {
            // 没有元素的迭代器是单调的。
            // 尽管这可能是一个哲学上的争论。
            true
        }
    }
}

fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
        println!(&quot;Is monotonic!&quot;);
    }
    println!(&quot;{:?}&quot;, v);
}
Is monotonic!
[1, 2, 3]
英文:

According to its documentation, Vec&lt;T&gt; implements the following IntoIterator traits:

  • IntoIterator&lt;Item = &amp;&#39;a T&gt; for &amp;&#39;a Vec&lt;T, A&gt;
  • IntoIterator&lt;Item = &amp;&#39;a mut T&gt; for &amp;&#39;a mut Vec&lt;T, A&gt;
  • IntoIterator&lt;Item = T&gt; for Vec&lt;T, A&gt;

The variable v you are calling it on is a Vec&lt;u32&gt;, which only implements IntoIterator&lt;Item = u32&gt;, and not any kind of &amp;&#39;a u32 as your trait requires.

There are a couple of solutions. The first one is to run the code on &amp;v:

trait Monotonic&lt;&#39;a, T: &#39;a + ?Sized&gt; {
    fn is_monotonic(&amp;mut self) -&gt; bool {
        return true;
    }
}

impl&lt;&#39;a, T: &#39;a + ?Sized, C&gt; Monotonic&lt;&#39;a, T&gt; for C where C: IntoIterator&lt;Item = &amp;&#39;a T&gt; + ?Sized {}

fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if (&amp;v).is_monotonic() {
        print!(&quot;Is monotonic!&quot;);
    }
}

Although that's probably not what you want, because I read from your question that you want your Monotonic trait to be implemented as generically as possible. For that, simply remove the &amp; requirement:

trait Monotonic&lt;&#39;a, T: &#39;a + ?Sized&gt; {
    fn is_monotonic(&amp;mut self) -&gt; bool {
        return true;
    }
}

impl&lt;&#39;a, T: &#39;a + ?Sized, C&gt; Monotonic&lt;&#39;a, T&gt; for C where C: IntoIterator&lt;Item = T&gt; + ?Sized {}

fn main() {
    let mut v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
        print!(&quot;Is monotonic!&quot;);
    }
}

Couple of remarks concerning your current code structure, though:

  • While this technically compiles, it won't be possible to implement your function. IntoIterator consumes the object you call it on, but your is_monotonic function only has &amp;mut access to it, so you won't ever be able to call into_iter here.

    What you probably want instead is to have is_monotonic consume the value, but then only implement it for &amp;T.

  • Your Monotonic function doesn't require any generic parameters, so remove them.

trait Monotonic {
    fn is_monotonic(self) -&gt; bool;
}

impl&lt;&#39;a, T, C&gt; Monotonic for &amp;&#39;a C
where
    &amp;&#39;a C: IntoIterator&lt;Item = T&gt;,
{
    fn is_monotonic(self) -&gt; bool {
        let mut iter = self.into_iter();

        // Do something with iter
        let x = iter.next().unwrap();

        // Return result
        true
    }
}

fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
        print!(&quot;Is monotonic!&quot;);
    }
}

Here is an example implementation of is_monotonic, assuming it means monotonic rising:

trait Monotonic {
    fn is_monotonic(self) -&gt; bool;
}

impl&lt;&#39;a, T, C&gt; Monotonic for &amp;&#39;a C
where
    &amp;&#39;a C: IntoIterator&lt;Item = T&gt;,
    T: PartialOrd,
{
    fn is_monotonic(self) -&gt; bool {
        let mut iter = self.into_iter();

        if let Some(first) = iter.next() {
            let mut previous = first;
            for next in iter {
                if !next.ge(&amp;previous) {
                    return false;
                }
                previous = next;
            }
            true
        } else {
            // An iterator without elements is monotonic.
            // Although that&#39;s probably up for philosophical debate.
            true
        }
    }
}

fn main() {
    let v = vec![1u32, 2u32, 3u32];
    if v.is_monotonic() {
        println!(&quot;Is monotonic!&quot;);
    }
    println!(&quot;{:?}&quot;, v);
}
Is monotonic!
[1, 2, 3]

huangapple
  • 本文由 发表于 2023年2月18日 19:20:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75492981.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定