我有一个包含函数对象的结构:
struct Foo<F> {
func: F,
}
Run Code Online (Sandbox Code Playgroud)
我想添加Fn绑定到结构定义的特征.问题是:我确实关心第一个参数(必须是i32),而不是第二个参数.我真正想写的是这样的:
struct Foo<F>
where
? P so that F: Fn(i32, P),
{
func: F,
}
Run Code Online (Sandbox Code Playgroud)
所以在英语中:类型F必须是一个带有两个参数的函数,第一个是i32(和第二个可以是任何东西).上面的语法显然无效.我想到了三个可能的解决方案:
该for<>语法不会帮助这里.除了它对非寿命参数不起作用的事实之外,它是通用的("为所有人")而不是存在的("存在").所以那就是了.
另一种可能性是向结构添加类型参数.我已经不喜欢那个解决方案了,因为参数本身并不属于struct.
struct Foo<F, P>
where
F: Fn(i32, P),
{
func: F,
}
Run Code Online (Sandbox Code Playgroud)
但是这不起作用:P除了where绑定之外没有使用参数,所以编译器会抱怨.
这个问题可以通过添加一个PhantomData<P>字段来解决,但这不是必需的,更重要的是,用户不能再轻易使用struct constructor语法了.
最后我试过这个:
struct Foo<F>
where
F: Fn(i32, _),
{
func: F,
}
Run Code Online (Sandbox Code Playgroud)
但这也行不通:
error[E0121]: the type placeholder `_` is not allowed within types on item signatures …Run Code Online (Sandbox Code Playgroud)use std::iter::Iterator;
trait ListTerm<'a> {
type Iter: Iterator<Item = &'a u32>;
fn iter(&'a self) -> Self::Iter;
}
enum TermValue<'a, LT>
where
LT: ListTerm<'a> + Sized + 'a,
{
Str(LT),
}
Run Code Online (Sandbox Code Playgroud)
error[E0392]: parameter `'a` is never used
--> src/main.rs:8:16
|
8 | enum TermValue<'a, LT>
| ^^ unused type parameter
|
= help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
Run Code Online (Sandbox Code Playgroud)
'a显然正在被使用.这是一个错误,还是参数枚举还没有真正完成?rustc --explain E0392建议使用PhantomData<&'a _>,但我认为在我的用例中没有任何机会这样做.
我一直在使用相当多的静态类型编程语言(C++、Haskell 等),但对 Rust 还比较陌生。
我经常最终编写这样的代码:
struct LeafNode<K: Ord + Default + Clone, V: Default + Clone> {
keys: Vec<K>,
values: Vec<V>,
}
impl <K: Ord + Default + Clone, V: Default + Clone> LeafNode<K, V> {
// ...
}
Run Code Online (Sandbox Code Playgroud)
这里的类型约束有很多重复。LeafNode当在其他东西中使用时(例如,在构建节点树时),情况会进一步复杂化。每当这些约束之一在实现过程中发生变化时,就有很多地方需要更改代码,因为它们在许多不同的struct定义和impl块中命名。
K: Ord + Default + Clone有没有办法从和创建某种“类型约束别名” V: Default + Clone?
如果它存在,它可能有一些我不知道的名称,这使得搜索该技术非常困难。于是就有了这个问题。
我有一个看起来像这样的特征:
trait Handler<C> {
fn handle(&self, msg: &Message, connection: &mut C);
}
Run Code Online (Sandbox Code Playgroud)
实例应该像链接HTTP处理程序的中间件一样被链接:
let handler = FirstHandler {
next: SecondHandler {
next: FinalHandler {},
},
};
Run Code Online (Sandbox Code Playgroud)
每种处理程序类型都可以对类型施加额外的约束C:
trait ConnectionThatWorksWithFirstHandler {
...
}
struct FirstHandler<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> {
next: H,
_phantom: PhantomData<C>,
}
Run Code Online (Sandbox Code Playgroud)
正如你在这里看到的,我需要一个PhantomData<C>避免错误E0392(parameter C is never used).但是,PhantomData在语义上是错误的,因为处理程序没有持有实例C.这很难看.例如,我手动必须提供正确的同步/发送特征实现:
unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Send for Handler<C, H> where H: Send {}
unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Sync for Handler<C, H> where H: …Run Code Online (Sandbox Code Playgroud) 我正在编写一些代码,我对延迟评估的函数链感兴趣。换句话说,它存储您想要的所有操作,并且只对它们进行一起评估。
当链中的所有函数都采用相同的类型并返回相同的类型时,这非常容易。然而,当函数链每次返回不同的类型时,我一直困惑于如何使其工作。这个简单的例子可以在下面的代码中看到:
struct FuncChain<T> {
funcs: Vec<fn(T) -> T>
}
impl<T> FuncChain<T> {
fn call(&self, input: T) -> T {
self.funcs.iter().fold(input, |prev, func| func(prev))
}
}
fn main(){
let fc = FuncChain {
funcs: vec![
|x| x + 1,
|x| x + 2,
|x| x * 2,
|x| x - 2,
]
};
println!("{}", fc.call(1));
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
所以在这种情况下我们就去i32 -> i32 -> i32 -> i32 -> i32。
我想做的是一个更一般的情况,我们去A -> B -> C -> D -> E …
我正在 Rust 中测试自定义双向迭代器,但遇到了错误
error[E0382]: borrow of moved value: `iter`
--> src/main.rs:40:13
|
37 | let mut iter = BiIterator::from(vec![1, 2, 3]);
| -------- move occurs because `iter` has type `BiIterator<i32>`, which does not implement the `Copy` trait
38 | for i in iter {
| ----
| |
| `iter` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&iter`
39 | if i == 3 {
40 | iter.position(0); …Run Code Online (Sandbox Code Playgroud) 我写了一个像这样的库:
struct Foo<A: AppleTrait, B: BananaTrait, C: CarrotTrait> {...}
impl<A: AppleTrait, B: BananaTrait, C: CarrotTrait> Foo<A,B,C> {...}
struct Bar<A: AppleTrait, B: BananaTrait, C: CarrotTrait> {...}
impl<A: AppleTrait, B: BananaTrait, C: CarrotTrait> Bar<A,B,C> {...}
... and many more...
Run Code Online (Sandbox Code Playgroud)
请注意,像这样的东西<A: AppleTrait, B: BananaTrait, C: CarrotTrait>总是聚在一起,并且出现了很多次。所以我想消除这样的负担。
因此,我希望我可以做这样的事情:
define_the_trait_alias ABCTrait = (A: AppleTrait, B: BananaTrait, C: CarrotTrait); // How to do this?
struct Foo<ABC: ABCTrait> {...}
impl<ABC: ABCTrait> Foo<ABC> {...}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在尝试创建一个通用的结构,该结构具有通用实现特征的界限。该特征本身是通用的。这是 Rust 1.49.0 中的内容。
如果我这样做:
trait Foo<T> {}
struct Baz<F: Foo<T>> {
x: F,
}
Run Code Online (Sandbox Code Playgroud)
我收到编译错误,因为T未定义。但如果我定义它:
trait Foo<T> {}
struct Baz<T, F: Foo<T>> {
x: F,
}
Run Code Online (Sandbox Code Playgroud)
然后我收到编译器错误,因为T未使用。
唯一的选择似乎是包含一个PhantomData<T>字段,但如果我的通用依赖性变得更加复杂,这就会开始变得更加笨拙:
use std::marker::PhantomData;
trait Foo<T> {}
struct Baz<T, U, F: Foo<T>, G: Foo<U>> {
phantom_t: PhantomData<T>,
phantom_u: PhantomData<U>,
x: F,
y: G,
}
Run Code Online (Sandbox Code Playgroud)
我的领域一半都是幻影!该结构实际上闹鬼。
我的问题是:最后的例子编译真的是惯用的 Rust 吗?如果是这样,为什么 Rust 无法检测到TinBaz<T, Foo<T>>确实被使用了?
我的函数是结构的一部分(出于上下文原因),它不接受参数self。此外,结构本身采用T带有一些特征限制的通用参数:
trait SomeRestriction {}
struct SomeStruct<T: SomeRestriction>(T);
impl<T: SomeRestriction> SomeStruct<T> {
fn some_function_that_does_not_take_self() -> String {
todo!()
}
}
Run Code Online (Sandbox Code Playgroud)
我想编写一个测试,并且想避免为该函数提供self参数,因为使用一些通用结构参数模拟对象对于该小函数和测试来说需要付出很大的努力。
我在其他测试中这样做,因为那里有必要,但我想尽可能避免它。
我尝试这样称呼它:
let some_string = SomeStruct::some_function_that_does_not_take_self();
Run Code Online (Sandbox Code Playgroud)
但它会要求我提供类型注释,即使不需要。
有没有办法在不模拟结构或从结构实现中删除函数的情况下调用它?
我无法让以下代码工作(游乐场:https://play.rust-lang.org/? version=stable&mode= debug&edition=2021&gist=4379c2006dcf3d32f59b0e44626ca667)。
use serde::{Serialize, Deserialize};
trait InnerStruct<'delife>: Deserialize<'delife> + Serialize {}
#[derive(Serialize, Deserialize)]
struct InnerStructA{
a: i32
}
impl InnerStruct<'_> for InnerStructA {}
#[derive(Serialize, Deserialize)]
struct InnerStructB{
a: i32,
b: i32
}
impl InnerStruct<'_> for InnerStructB {}
#[derive(Serialize, Deserialize)]
struct OuterStruct<T: InnerStruct>{ // Remove the word "InnerStruct" and this works
c: f64,
inner: T
}
fn print_json<T: for<'a> InnerStruct<'a>>(obj: T) {
println!("Serde JSON: {:?}", serde_json::to_string(&obj).unwrap());
}
fn main() {
let inner_a = InnerStructA{a: 123};
let inner_b = InnerStructB{a: …Run Code Online (Sandbox Code Playgroud) 假设我想编写一个 HashMap 包装器。我的尝试:
struct Wrapper<K,V> where HashMap<K,V>: Default{
value: HashMap<K,V>
}
Run Code Online (Sandbox Code Playgroud)
我希望 K,V 隐式地具有使 HashMap<K,V> 有效的任何边界。是否有比默认更好的特征可以更好地传达这一意图?像 HashMap<K,V>: True 之类的东西?