我有一个函数f
,应该如下所示:
struct S;
let s = &S;
f(&[(s, &[0.1, 0.2, 0.3]), (s, &[0.5, 0.6])]);
为了方便界面,我希望f
能够处理任何类型的IntoIterator
。目前,我的签名是
fn f<'a, I, J: 'a>(iter: I)
where
I: IntoIterator<Item = &'a (&'a S, J)>,
J: IntoIterator<Item = &'a f32>
遗憾的是,编译器将切片视为固定大小的数组,因此我得到了以下错误:
error[E0308]: mismatched types
--> sandbox/src/main.rs:142:33
|
142 | f(&[(s, &[0.1, 0.2, 0.3]), (s, &[0.5, 0.6])]);
| ^^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
|
= note: expected type `&[{float}; 3]`
found type `&[{float}; 2]`
用J
代替Vec<f32>
可以工作,但这不是我想要的方式。
有办法处理这个问题吗?这样我就可以像前面提到的那样调用这个函数了吗?起初,我认为可以用高等级特征界来解决这个问题,但是这些只能用于生命周期参数。
如果它可以工作,我如何正确地处理这些嵌套IntoIterator
?我如何打电话给J::into_iter()
发布于 2018-02-26 15:44:48
函数定义非常好;问题是如何构造参数。如果没有该功能,它也无法工作:
41 | let x = &[(s, &[0.1, 0.2, 0.3]), (s, &[0.5, 0.6])];
| ^^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
|
= note: expected type `&[{float}; 3]`
found type `&[{float}; 2]`
编译器看到外部切片的第一个元素,并推断该切片具有(&S, &[{float}; 3])
类型的元素。这与长度为2的第二个元素相冲突,它根本不知道是否可以/应该使用更通用的任意切片&[{float}]
。
如果我们显式地强制第一个元素的类型,它会编译得很好:
f(&[(s, &[0.1f32, 0.2, 0.3] as &[f32]), (s, &[0.5, 0.6])]);
或者,您可以传递迭代器,这也方便地实现了IntoIterator
。
f(&[(s, [0.1, 0.2, 0.3].iter()), (s, [0.5, 0.6].iter())]);
诚然,这两种做法都不是特别方便(尽管后者并不是很糟糕的海事组织)。如果目标是拥有一个接受嵌套切片的函数,您可以这样定义它:
fn f2<T>(iter: &[(&S, &[T])]) {}
f2(&[(s, &[0.1, 0.2, 0.3]), (s, &[0.5, 0.6])]);
您必须选择权衡:要么有一个函数可以方便地获取切片,但拒绝其他可迭代性,要么有一个函数需要任何迭代,但调用起来稍微麻烦一些。
如果您的函数使用新的impl Trait
-syntax,则此建议也适用:
fn f<'a>(iter: impl IntoIterator<Item = &'a (&'a S, impl IntoIterator<Item = &'a f32> + 'a)>)
https://stackoverflow.com/questions/48987501
复制相似问题