如何指定 Rust 特征边界的多种可能性

问题描述 投票:0回答:1

我正在尝试编写一个函数,它将任何可迭代的泛型类型作为输入并循环遍历元素。这是一个工作示例

 pub fn test1<'a, IterableT, ItemT>(nodes: &'a IterableT)
    where 
        &'a IterableT: IntoIterator<Item = &'a ItemT>,
        ItemT: 'a + Debug
    {
        for x in nodes {
            println!("consuming or iterating: {:?}!", x);
        }
    }

这适用于引用类型。我努力实现一个既适用于常规类型又适用于引用的版本。我得到的最接近的是以下

 pub fn test1<IterableT>(nodes: IterableT)
    where 
        IterableT: IntoIterator,
        IterableT::Item: Debug
    {
        for x in nodes {
            println!("consuming or iterating: {:?}!", x);
        }
    }

只要我使用的类型的参考版本实现了 IntoIterator(例如

vec
&vec
&mut vec
),此方法就有效。问题是我无法重新引入
ItemT
泛型,因为那时底层
Item
已缩小为
Item
&Item

之一
 pub fn test1<IterableT, ItemT>(nodes: IterableT)
    where 
        IterableT: IntoIterator<Item = ItemT>, // alternatively IntoIterator<Item = &ItemT>
        ItemT: Debug
    {
        for x in nodes {
            println!("consuming or iterating: {:?}!", x);
        }
    }

根据我使用的是

IntoIterator<Item = ItemT>
还是
IntoIterator<Item = &ItemT>
,这适用于
vec
&vec
,但不能同时使用。一个巧妙的解决方法是指定
IterableT::Item: Into<ItemT>
,但这仅在底层类型实现 Into 特征时才有效(因此这适用于 i32、i64 等内置类型,但不适用于某些自定义结构)。

有没有办法表明

Item
可以是
ItemT
&ItemT
子句中的
where
?我需要引入
ItemT
的原因是因为它是该函数所属父结构的通用变量。我需要专门接受该类型的迭代器。

rust traits trait-bounds
1个回答
0
投票

您可以使用

std::borrow::Borrow
来治疗
T
&T
一样。

use std::{borrow::Borrow, fmt::Debug};

fn debug_iterator<I, T>(it: I)
where
    I: IntoIterator,
    I::Item: Borrow<T>,
    T: Debug + ?Sized,
{
    for item in it.into_iter() {
        println!("  item: {:?}", item.borrow());
    }
}

行动中:

fn main() {
    let v1 = vec![String::from("hello"), String::from("world")];

    println!("By reference:");
    debug_iterator::<_, String>(v1.iter());
    
    println!("By value:");
    debug_iterator::<_, String>(v1);
}

输出:

By reference:
  item: "hello"
  item: "world"
By value:
  item: "hello"
  item: "world"

请注意,由于

Borrow
特征具有类型参数,因此您必须在调用站点显式地为
T
提供正确的类型; Rust 将无法推断出你想要的类型。

© www.soinside.com 2019 - 2024. All rights reserved.