[英]How can I specify that a trait function takes an argument implementing the trait?
[英]How to specify generics that can be dereferenced into a trait
我有结构A
和B
,其中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.