Rust 如何为函数提供仅限类型的参数?

Rust 如何为函数提供仅限类型的参数?,rust,Rust,在我短暂的生锈经验中,我多次遇到这种模式,我不确定我解决它的方法是否真的足够 让我们假设我有如下特点: trait Container { type Item; fn describe_container() -> String; } trait Item { type C: Container; } fn describe_item_container<I: Item>(item: I) -> String { I::C::descri

在我短暂的生锈经验中,我多次遇到这种模式,我不确定我解决它的方法是否真的足够

让我们假设我有如下特点:

trait Container {
    type Item;
    fn describe_container() -> String;
}
trait Item {
    type C: Container;
}
fn describe_item_container<I: Item>(item: I) -> String {
    I::C::describe_container()
}
以及一些实现此特性的结构:

struct ImAContainerType;
struct ImAnItemType;
impl Container for ImAContainerType {
    type Item = ImAnItemType;
    fn describe_container() -> String { "some container that contains items".to_string() }
}
这可能是一个容器,它知道它所包含的项的类型,如本例中所示,或者,作为另一个示例,它知道应该返回什么类型的响应,等等

现在我发现自己处于一种情况下,当我需要实现一个函数,该函数接受一个项(关联的类型)并调用容器的一个静态函数(父特性)。这是第一次天真的尝试:

fn describe_item_container<C: Container>(item: C::Item) -> String {
    C::describe_container()
}
编译。。。错误:

error[E0277]: the trait bound `std::marker::PhantomData<ImAContainerType>: Container` is not satisfied
它应该可以工作,但会使事情变得更加复杂(特别是当物品可以放在不同的容器中时)

经过更多的实验后,我做了以下更改,所有内容都能正确编译和工作:

let s = describe_item_container(PhantomData::<ImAContainerType>, ImAnItemType);
println!("{}", s);
let s=description_item_容器(PhantomData::,ImAnItemType);
普林顿!(“{}”,s);
更改是

这是可行的,但现在我完全糊涂了。这是使用幻影数据的正确方法吗?为什么它能工作呢?是否有其他更好的方法为Rust中的函数提供纯类型参数



EDIT:在我的示例中有一些过于简单化的地方,因为在这种特殊情况下,只调用
ImAContainerType::description_container()
会更容易。当函数实际使用
项执行某些操作时,仍然需要容器类型信息。

如果要将类型参数传递给函数,可以这样做。你不必把它排除在外以供推断

下面是第二个示例()的外观:

fn pack\u item(item:C::item)->itempack{
项目包{
容器描述:C::描述容器(),
_有效负载:item.get_payload(),
}
}
fn main(){
设s=包装项目::(ImAnItemType);
println!(“{}”,s.container_description);
设s=包装项目::(ImAnItemType);
println!(“{}”,s.container_description);
}

这不会编译-。我遗漏了什么?@Shepmaster:如果你真的从
main()
调用该函数,我不确定这是不是正确的方法;你想要实现什么?如果您需要一个包含泛型成员的容器,为什么不让某个成员
T
,例如,在需要时使用以获取其具体类型?使用关联类型似乎不是一个好办法。@ljedrz关联类型提供编译时保证。您是对的,可以在运行时使用
get\u type\u id()
动态检查它,但如果可能的话,我更喜欢静态限制。谢谢!这似乎是我错过的Rust语法特性。这有点麻烦,因为如果我想指定一个类型参数,我必须指定所有其他类型参数,即使是那些可以由编译器推断的参数,但它工作得很好@谢尔盖米茨基维奇
let s = describe_item_container(PhantomData::<ImAContainerType>, ImAnItemType);
println!("{}", s);
fn pack_item<C: Container>(item: C::Item) -> ItemPacket {
    ItemPacket {  
        container_description: C::describe_container(),
        _payload: item.get_payload(),
    }
}

fn main() {
    let s = pack_item::<ImAContainerType>(ImAnItemType);
    println!("{}", s.container_description);
    let s = pack_item::<ImAnotherContainerType>(ImAnItemType);
    println!("{}", s.container_description);
}