Двоичная операция!= Не может быть применена при использовании обобщенных значений для битового вектора

Я нахожусь в процессе реализации класса Bit Vector в качестве упражнения, однако, зная Rust менее недели, я столкнулся с проблемой следующего кода:

use std::cmp::Eq;
use std::ops::BitAnd;
use std::ops::Index;
use std::ops::Not;

struct BitVector<S = usize> 
    where S: Sized + BitAnd<usize> + Not + Eq {
    data: Vec<S>,
    capacity: usize
}

impl<S> BitVector<S>
    where S: Sized + BitAnd<usize> + Not + Eq {
    fn with_capacity(capacity: usize) -> BitVector {
        let len = (capacity / (std::mem::size_of::<S>() * 8)) + 1;
        BitVector { data: vec![0; len], capacity: capacity }
    }
}

impl<S> Index<usize> for BitVector<S>
    where S: Sized + BitAnd<usize> + Not + Eq {
    type Output = bool;

    fn index(&self, index: usize) -> &bool {
        let data_index = index / (std::mem::size_of::<S>() * 8);
        let remainder = index % (std::mem::size_of::<S>() * 8);
        (self.data[data_index] & (1 << remainder)) != 0
    }
}

Идея в том, что S может быть одним из например u8, u16, u32, u64 а также usize чтобы установить его на 0 в with_capacity создает битовое значение для S это состоит из всех нулей.

Я получаю следующую ошибку:

lib.rs:27:10: 27:50 ошибка: бинарная операция != нельзя применять к типу <S as std::ops::BitAnd<usize>>::Output [E0369]
lib.rs:27 (self.data[data_index] & (1 << остаток))! = 0
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lib.rs:27:10: 27:50 help: run rustc --explain E0369 чтобы увидеть подробное объяснение
lib.rs:27:10: 27:50 примечание: реализация std::cmp::PartialEq может отсутствовать для <S as std::ops::BitAnd<usize>>::Output
lib.rs:27 (self.data [data_index] & (1<< Остаток))!= 0 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ошибка: прерывание из-за предыдущей ошибки
ошибка: не удалось скомпилировать bit-vector,

1 ответ

Решение

Эта конкретная ошибка здесь, в простых терминах, означает, что Output из BitAndИНГ S а также usize не реализует PartialEq, Одним из исправлений было бы добавить ограничение, которое S"s BitAnd<usize>s Output является S:

BitAnd<usize, Output = S>

После этого вы столкнетесь с другой ошибкой, потому что вы сравниваете значение BitAnd с 0 а не к значению типа S, Чтобы исправить это, вы можете определить свой собственный Zero черт и использовать это или использовать нестабильный Руст std::num::Zero и сравнить с S::zero(),

Вам также придется сделать S: Copy так что делать BitAnd не потребляет значение (или добавить S: Clone и явно клонировать перед вызовом BitAnd::bitand).

Наконец вы столкнетесь с ошибкой, что ваш index должен вернуть &bool пока вы возвращаете bool, Вы можете использовать хитрость bit-vec, чтобы определить 2 статики:

static TRUE: bool = true;
static FALSE: bool = false;

и вернуться &TRUE или же &FALSE от index,

Окончательный рабочий (по Ночному) код:

#![feature(zero_one)]

use std::cmp::Eq;
use std::num::Zero;
use std::ops::BitAnd;
use std::ops::Index;
use std::ops::Not;

struct BitVector<S = usize>
    where S: Sized + BitAnd<usize, Output = S> + Not + Eq + Copy + Zero
{
    data: Vec<S>,
    capacity: usize,
}

impl<S> BitVector<S>
    where S: Sized + BitAnd<usize, Output = S> + Not + Eq + Copy + Zero
{
    fn with_capacity(capacity: usize) -> BitVector {
        let len = (capacity / (std::mem::size_of::<S>() * 8)) + 1;
        BitVector {
            data: vec![0; len],
            capacity: capacity,
        }
    }
}

static TRUE: bool = true;
static FALSE: bool = false;

impl<S> Index<usize> for BitVector<S>
    where S: Sized + BitAnd<usize, Output = S> + Not + Eq + Copy + Zero
{
    type Output = bool;

    fn index(&self, index: usize) -> &bool {
        let data_index = index / (std::mem::size_of::<S>() * 8);
        let remainder = index % (std::mem::size_of::<S>() * 8);
        if (self.data[data_index] & (1 << remainder)) != S::zero() {
            &TRUE
        } else {
            &FALSE
        }
    }
}

fn main() {
}
Другие вопросы по тегам