繁体   English   中英

如何指定可以取消引用到特征中的泛型

[英]How to specify generics that can be dereferenced into a trait

我有结构AB ,其中B可以取消引用到A

A使用函数.get_value()实现GetValue ,因此B也间接实现GetValue

现在我想写一个函数print_value可以接受&A&B ,所以它可以在内部调用.get_value() 从技术上讲,这应该是可能的,因为它们都可以取消引用到&GetValue &A通过取消引用一次, &B通过取消引用两次。

问题是:如何指定print_value的泛型来实现这一点?


这是我的尝试:

use std::ops::Deref;

//### external library code ######################
struct A(i32);
struct B(A);

impl Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

trait GetValue {
    fn get_value(&self) -> i32;
}

impl GetValue for A {
    fn get_value(&self) -> i32 {
        self.0
    }
}

//### my code ####################################
fn print_value<T: Deref>(val: T)
where
    <T as Deref>::Target: GetValue,
{
    println!("{}", val.get_value())
}

fn main() {
    let a = A(1);
    let b = B(A(2));

    println!("{}", a.get_value());
    println!("{}", b.get_value());

    print_value(&a);
    print_value(&b); // < fails with error "the trait bound `B: GetValue` is not satisfied"
}

这里的问题是<T as Deref>::Target: GetValue不匹配&B ,因为&B必须被取消引用两次。 调用函数时编译器会自动多次取消引用,那么有没有办法通过泛型来实现呢?


笔记

我只有执行print_value的权力。 我没有其他功能的权力。

一个更真实的例子是:

  • get_value = get_error_source
  • A = 错误类型
  • B = Box<dyn A>
  • GetValue = std::error::Error

我只是想让它尽可能抽象以避免混淆。 我仍然很确定这不是 XY 问题。

与其让一个函数有一个过于复杂的签名来表示它可以获取你知道的任何东西来get_value值,你可以做一个全面的实现。 这样,您会自动表示您可以get_value of,嗯,您可以get_value of。

impl<T> GetValue for T
where
    T: Deref,
    <T as Deref>::Target: GetValue,
{
    fn get_value(&self) -> i32 {
        self.deref().get_value()
    }
}

只需添加它即可使其工作, 请参阅操场

您只需要在对象上实际调用deref ,然后您将传递B&A

use std::ops::Deref;

...

fn print_value<T: Deref>(val: T)
where
    <T as Deref>::Target: GetValue,
{
    println!("{}", val.deref().get_value())
}

fn main() {
    let a = A(1);
    let b = B(A(2));

    println!("{}", a.get_value());
    println!("{}", b.get_value());

    print_value(&a);
    print_value(b); 
}

操场

输出:

1
2
1
2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM