2017-02-28 43 views
3

我正在学习Rust的过程。我发现“过度工程”玩具的例子在早期阶段是一件有用的事情,这导致了我的这种状况。类型参数与std :: ops :: BitXor类型不匹配输出关联类型

这个简单的功能开始:

extern crate data_encoding; 

use std::ops::BitXor; 
use data_encoding::hex; 
use std::iter::FromIterator; 


fn fixed_xor_basic(l: &[u8], r: &[u8]) -> Vec<u8> { 
    l.iter().zip(r.iter()).map(|(x, y)| *x^*y).collect() 
} 

#[test] 
fn test_fixed_xor_basic() { 
    let input_1 = hex::decode(b"1C0111001F010100061A024B53535009181C").unwrap(); 
    let input_2 = hex::decode(b"686974207468652062756C6C277320657965").unwrap(); 

    let expected_output = hex::decode(b"746865206B696420646F6E277420706C6179").unwrap(); 

    assert_eq!(fixed_xor_basic(&input_1, &input_2), expected_output); 
} 

我移动到一个简单的变体摆脱分配:

fn fixed_xor_basic_inplace(l: &mut [u8], r: &[u8]) { 
    for (left, right) in l.iter_mut().zip(r.iter()) { 
     *left = *left^*right; 
    } 
} 

而另一个接受可异或任何类型:

fn fixed_xor_generic<T>(l: &[T], r: &[T]) -> Vec<T> 
    where T: BitXor + Copy, 
      Vec<T>: FromIterator<<T as BitXor>::Output> { 
    l.iter().zip(r.iter()).map(|(x, y)| *x^*y).collect() 
} 

这第二个变体最初没有编译 - 但错误消息暗示我病房增加了约束条件Vec<T>: FromIterator<<T as BitXor>::Output>。大概这个约束给了编译器一些暗示BitXor::Output实际上与T是一样的,但我不清楚这个提示是什么。现在

...两者结合有我难住了:

fn fixed_xor_generic_inplace<T>(l: &mut [T], r: &[T]) 
    where T: BitXor + Copy { 
    for (left, right) in l.iter_mut().zip(r.iter()) { 
     *left = *left^*right; 
    } 
} 

产生一个错误:

error[E0308]: mismatched types 
    --> src/xor_lib.rs:27:17 
    | 
27 |   *left = *left^*right; 
    |     ^^^^^^^^^^^^^^ expected type parameter, found associated type 
    | 
    = note: expected type `T` 
    = note: found type `<T as std::ops::BitXor>::Output` 

error: aborting due to previous error 

强烈怀疑这两种情况都差不多,我需要提供一些额外的上下文帮助编译器找出T实际上是<T as std::ops::BitXor>::Output的另一个名字。

我在正确的轨道上吗?如果是这样,这个提示是什么?

(下一个挑战是让函数接受IntoIterator类型而不是切片 - 如果这可能会影响解决方案)。

回答

2

您只需告诉编译器,关联的类型OutputT相同。

fn fixed_xor_generic_inplace<T>(l: &mut [T], r: &[T]) 
    where T: BitXor<Output = T> + Copy { 
    for (left, right) in l.iter_mut().zip(r.iter()) { 
     *left = *left^*right; 
    } 
} 
+0

那好容易!这也简化了第一个通用示例'Vec :FromIterator < :: Output>'不再是必需的。谢谢! – jdeastwood