2017-02-22 99 views
3

Я хочу написать некоторые общие математические функции, не предполагая, что мои типы можно копировать. Это кажется невозможным, поскольку математические операторы потребляют значения вместо их заимствования. Поэтому требуется скопировать объект, просто для простой математики. Я мог бы просто переместить их, но это невозможно в заимствованном контексте, который мне нужен, когда я хочу мутировать структуру.Общая математика без копирования в ржавчине

Вот несколько простых примеров, где есть проблемы:

use std::ops::Add; 

struct NoCopy<T>(T); //some non-copyable struct, (maybe a vector) 
struct Cont<T>(NoCopy<T>); //some struct contaioning a noncopyable struct 

impl<T: Add<Output=T>> Add for NoCopy<T> { 
    type Output = NoCopy<T>; 
    fn add(self, x: NoCopy<T>) -> NoCopy<T> { 
     NoCopy(self.0+x.0) 
    } 
} 

fn main() { 
    let x = NoCopy(1); 
    let cont = Cont(x); 
    let rel = NoCopy(2); 
    cont.0=cont.0+rel; //addition makes struct cont invalid, so i have to copy 
} 

И когда я просто хочу, чтобы вычислить что-то с не Copyable объектом структуры (например, длина вектора), он не будет работа, поскольку значение будет либо потребляться, поэтому структура становится недействительной, либо контролер заимствования говорит, что «не может выйти из заимствованного контекста». Как правильно использовать общую математику при мутировании структур? Это возможно только для типов копирования (или явного клонирования)?

+0

Я не совсем уверен, что по этому вопросу, но мой первый мысль состоит в том, что 'Cont' сам не имеет оператора Add - только объекты NoCopy' - даже мысль' Cont' - это то, что вы добавляете к 'NoCopy'? Другой вариант может заключаться в том, что 'cont' mutable и имеет' cont = Cont (cont.0 + rel) '? –

+0

Это просто пример. В реальности такой способ может быть проблематичным, поскольку у меня есть много полей в моей структуре, а также хочу использовать его в заимствованных контекстах – porky11

ответ

9

Одним из вариантов является реализация Add на ссылках:

impl<'a, T: Copy + Add<Output = T>> Add for &'a NoCopy<T> { 
    type Output = NoCopy<T>; 
    fn add(self, rhs: Self) -> NoCopy<T> { 
     NoCopy(self.0+rhs.0) 
    } 
} 

Это нормально, так как общие ссылки Copy. Примечание. Я добавил ограничение Copy в T, чтобы сделать эту реализацию простой (true для целых чисел); если T не является копией, то может потребоваться изменить метод однострочного перевода.

Вы должны добавить ссылки при использовании его, что это позор, но в противном случае работает:

fn main() { 
    let x = NoCopy(1); 
    let mut cont = Cont(x); 
    let rel = NoCopy(2); 
    cont.0=&cont.0+&rel; 
} 

(Playground)