generics - 如何表示返回的关联类型实现了特征?

标签 generics rust traits

这是显示我的问题的抽象示例,提取 self 重构一些 Rust 代码并同时学习 Rust 的尝试。

struct GenStruct<T> {
    field: T,
}

trait Marker {}
trait Return {}

impl Marker for i32 {}
impl Marker for u32 {}

// actually implement `Return` for GenStruct<M: Marker>,
// but compiler don't recognize that
impl Return for GenStruct<i32> {}
impl Return for GenStruct<u32> {}

struct Fake;

trait Trait<M: Marker> {
    type Ret: Return;
    fn meth(m: M) -> Self::Ret;
}

impl<M: Marker> Trait<M> for Fake {
    type Ret = GenStruct<M>;

    fn meth(m: M) -> GenStruct<M> {
        GenStruct { field: m }
    }
}

输出:

error[E0277]: the trait bound `GenStruct<M>: Return` is not satisfied
  --> src/lib.rs:23:17
   |
23 | impl<M: Marker> Trait<M> for Fake {
   |                 ^^^^^^^^ the trait `Return` is not implemented for `GenStruct<M>`
   |

编译器没有识别出我实际实现了 Return对于每个 GenStruct<M>其中 M 是 Marker .要修复它,我可以这样写:

trait Marker {
    fn is_i32() -> bool;
}
trait Return {
    fn ret();
}

impl Marker for i32 {
    fn is_i32() -> bool {
        true
    }
}
impl Marker for u32 {
    fn is_i32() -> bool {
        false
    }
}

// compiler is satisfied by such implementation
impl<M: Marker> Return for GenStruct<M> {
    fn ret() {
        if M::is_i32() {
        } else {
        }
    }
}

或者使用特征对象:

impl<M: Marker> Return for GenStruct<M> {}

trait Trait<'a, M: Marker + 'a> {
    fn meth(m: M) -> Box<Return + 'a>;
}

impl<'a, M: Marker + 'a> Trait<'a, M> for Fake {
    fn meth(m: M) -> Box<Return + 'a> {
        Box::new(GenStruct { field: m })
    }
}

但是,如果我使用特征对象,我无法编写 Return 的专门实现对于 GenStruct<i32>GenStruct<u32> .

编译器能否识别出我实现了 GenStruct<M: Marker>还是我的代码不是惯用的 Rust?如果我的代码不符合地道,那么正确的编写方式是什么?

最佳答案

使用 where子句,我们可以在通用 impl 上添加额外的约束所以它只适用于 GenStruct<M>确实实现了 Return .

impl<M: Marker> Trait<M> for Fake
where
    GenStruct<M>: Return,
{
    type Ret = GenStruct<M>;

    fn meth(m: M) -> GenStruct<M> {
        GenStruct { field: m }
    }
}

Rust 1.33 甚至通过帮助文本表明了这一点:

   = help: consider adding a `where GenStruct<M>: Return` bound

关于generics - 如何表示返回的关联类型实现了特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35343839/

相关文章:

c++ - 为可能包含或不包含指针的列表类中的泛型方法禁用编译器警告 2100

arrays - 使用切片和使用对数组的引用作为参数有什么区别?

rust - 定义一个结构体,其中只能默认某些字段

rust - 为什么这些场景会编译并创建悬挂指针?

scala - 当混合具有冲突的抽象覆盖的多个特征时,我如何预测将选择哪个实现?

c# - 为什么 C# 不支持变体泛型类?

ios - 通用协议(protocol) Swift 4 错误

performance - 如何使用对键的引用更新 HashMap 中的条目?

scala - `super` 是否静态绑定(bind)在类中?

rust - 除非我使用临时变量,否则为什么我不能插入 Vec 的 dyn Trait?