Автоматически пересылать операции, сохраняя результат - PullRequest
0 голосов
/ 10 ноября 2018

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

То, что у меня до сих пор выглядит примерно так:

pub trait Measure {
    type Underlying: Clone; // the underlying storage type (most often a Float)

    fn name() -> &'static str;
    fn default_unit() -> &'static str;
    fn in_default_unit(&self) -> Self::Underlying;
    fn from_default_unit(m: Self::Underlying) -> Self;
}

и реализация будет выглядеть примерно так:

#[derive(Debug, Clone, PartialEq)]
pub struct Angle<'a> {
    radians: Float, // dynamic but either a `f64` or `f32`
}

impl<'a> Angle<'a> {
    fn from_radians(radians: Float) -> Self {
        Self { radians }
    }
}

impl<'a> Measure<'a> for Angle<'a> {
    type Underlying = Float;

    fn name() -> &'static str {
        "angle"
    }

    fn default_unit() -> &'static str {
        "radian"
    }

    fn in_default_unit(&self) -> Self::Underlying {
        self.radians
    }

    fn from_default_unit(m: Self::Underlying) -> Self {
        Self::from_radians(m)
    }
}

Я хочу добавить общие операции, такие как перегрузка оператора + и аналогичные, но я хочу сделать это таким образом, чтобы он был связан с чертой Measure, поэтому мне не нужно создавать его для каждого Measure.

Я пытался создать промежуточный класс для операций, которые Angle могли бы Deref, но столкнулись с некоторыми проблемами со временем жизни, и я думаю, что этот маршрут на самом деле может быть невозможен.

Мне кажется, что это достаточно распространенная потребность, что есть решение. Как я могу это сделать?

1 Ответ

0 голосов
/ 12 ноября 2018

Существует несколько способов сделать это, в первую очередь, с использованием макросов или процедурных макросов.Этот метод на самом деле довольно хорошо описан в одном из ответов Шепмастера , но маршрут, который я собираюсь выбрать, вероятно, будет использовать ящик diverve_more , который позволит мне очень легко обеспечить эти удобствафункции.

Тогда я могу просто

#[macro_use]
extern crate derive_more;

#[derive(Add)]
struct Angle {
    radians: Float,
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...