gpt4 book ai didi

rust - 在 Rust 中实现类似于 C+ +'s ` std::remove_reference` 的东西?

转载 作者:行者123 更新时间:2023-11-29 07:43:24 25 4
gpt4 key购买 nike

如果类型是引用,我希望有一个工具可以从该类型中删除引用。像这样(伪代码):

remove_ref(i32)      == i32
remove_ref(&i32) == i32
remove_ref(&&i32) == i32
remove_ref(&mut i32) == i32

C++ 有 std::remove_reference在标准库中,它可以做我想做的。我试图在 Rust 中实现相同的功能,但我无法让它工作。现在,在 Rust 中“输出”类型的唯一方法是特征上的关联类型(我认为)。我试过这样的事情(Playground):

#![feature(specialization)]

trait RemoveRef {
type WithoutRef;
}

default impl<T> RemoveRef for T {
type WithoutRef = T;
}

impl<'a, T: RemoveRef> RemoveRef for &'a T {
type WithoutRef = T::WithoutRef;
}

事实上,这是可以编译的。有希望! (是的,这还没有考虑可变引用)。然而,当我尝试使用它时,一切都爆炸了:

let _: <i32 as RemoveRef>::WithoutRef = 3;
let _: <&i32 as RemoveRef>::WithoutRef = 3;
let _: <&&i32 as RemoveRef>::WithoutRef = 3;

第一行导致“溢出评估需求 i32: RemoveRef”。另外两行产生错误“特性绑定(bind) &i32: RemoveRef 不满足”。我不确定我是否只是不明白这一点,或者特化是否被打破了。 (相关:我用非常相似的代码得到了另一个奇怪的错误 here )

我在考虑实现这个的其他可能性:也许在特征上放置一个类型参数?也许 GAT 可以在这里提供帮助?语言中是否还有其他功能允许从一种类型映射到另一种类型?

有什么方法可以在 Rust 中实现这样的东西吗?

最佳答案

这里有一个简单的方法,可以在没有特化功能的情况下工作:

use std::marker::PhantomData;

trait RemoveRef {
type WithoutRef;
}

struct Ref<T> {
phantom: PhantomData<T>,
}

impl<T> RemoveRef for Ref<T> {
type WithoutRef = T;
}

impl<'a, T: RemoveRef> RemoveRef for &'a T {
type WithoutRef = T::WithoutRef;
}

fn main() {
let _: <Ref<i32> as RemoveRef>::WithoutRef = 3;
let _: <&Ref<i32> as RemoveRef>::WithoutRef = 3;
let _: <&&&&Ref<i32> as RemoveRef>::WithoutRef = 3;
}

但不确定它是否可以以这种形式与您的实际用例兼容,或者它是否有用。

或者,当然也可以用具体类型的实现替换通用退出条件(impl<T> RemoveRef for T):

impl RemoveRef for i32 {
type WithoutRef = Self;
}

这会启用您的原始测试代码:

let _: <i32 as RemoveRef>::WithoutRef = 3;
let _: <&i32 as RemoveRef>::WithoutRef = 3;
let _: <&&i32 as RemoveRef>::WithoutRef = 3;

AFAIK 专业无法帮助您解决重叠问题,例如 for T 之间的问题和 for &'a T在此刻。它需要诸如负特征界限之类的特征。

default impl 中的所有项目是默认的。如果你移动 default将关键字添加到代码中的关联类型可以消除计算溢出,但会出现其他错误:

impl<T> RemoveRef for T {
default type WithoutRef = T;
}
error[E0308]: mismatched types
--> src/main.rs:16:45
|
16 | let _: <i32 as RemoveRef>::WithoutRef = 3;
| ^ expected associated type, found integral variable
|
= note: expected type `<i32 as RemoveRef>::WithoutRef`
found type `{integer}`

失败的原因与此处讨论的相同:Mismatch between associated type and type parameter only when impl is marked default 正在分配 TWithoutRef结合 default不约束WithoutRef输入 T .

关于rust - 在 Rust 中实现类似于 C+ +'s ` std::remove_reference` 的东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51026536/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com