我有一个可以定义整数类型的小库.这些是为了在我经常编写的算法中对数组和字符串进行类型安全的索引.例如,我可以用它来定义一个偏移类型Offset
和一个索引类型Idx
,这样你可以通过减go 两个Idx
得到一个Offset
,你可以通过加或减Offset
得到Idx
,但是你不能,例如,乘以或加Idx
.
let (i,j): (Idx,Idx) = ...;
let offset: Offset = j - i; // Subtracting indices gives an offset
let k: Idx = j + offset; // Adding an offset to an index gives an index
// let _ = i + j; -- You can't add indices
我设法(with some difficulty)实现了std::iter::Step
,因此我还可以迭代一系列索引
for k in i .. j { /* ... */ }
但现在我已经着眼于一个更高的目标:我还想使用这些类型的范围来分割序列
let v: Vec<sometype> = vec![...];
let w: &[sometype] = &v[i..j]; // Slice with a range of Idx
这应该是实现std::ops::Index
和std::ops::IndexMut
的简单问题,只是类型系统不允许我实现
impl<I,T> std::ops::Index<std::ops::Range<I>> for Vec<T>
where I: /* my types */
{ ... }
对于包装器类型或泛型
impl<I,T> std::ops::Index<std::ops::Range<Wrapper<I>>> for Vec<T>
where I: /* my types */
{ ... }
其中Wrapper
是我实际使用的类型,I
是帮助我编写通用代码的特征.
问题是Index
和Range
都是在我的 crate 之外定义的,所以这种专业化是不允许的.还是这样?
当泛型类型的泛型参数来自于我的 crate 时,有什么方法可以在我的 crate 之外实现泛型类型的特征吗?
或者,更好的是,有没有办法利用..
运算符的语法糖分,这样我就可以得到一个包装类型?我想要的是包装Range
,以获得相同的行为,然后一些.我可以通过包装Range
和实现Deref
来实现这一点,但如果我这样做,我就失go 了..
操作符的语法优势.
这不是一个大问题,但我可以想象当你会写作时会有一些困惑
for k in i .. j { /* ... */ }
就像内置类型一样,但必须使用
let w: &[type] = &v[range(i,j)];
用于切片.如果我想让像i..
、..j
这样的切片包起来,那就更麻烦了.(..
片在这里无关紧要,反正也不会得到我想要的类型).如果我这样做了,我将需要三种类型的范围的构造函数,或者一些丑陋的包装使用Option
,我想.
..
语法糖真的很好,但从我探索的内容来看,你不能对自己类型的范围使用那么多.你可以定义范围,通过一些黑客攻击,你可以迭代它们,但你不能用它们建立索引.
告诉我我错了,或者让我知道是否有什么技巧可以完成工作,甚至完成一半.或者,如果这确实不可能,请告诉我,这样我就可以停止在上面浪费时间,编写一个包装器类,放弃..
运算符.
Update我在playgrounds中举了一个简化的例子