#type #constant #polymorphism #overflow #const

多态常量

一次定义多种类型中的数值常量的宏

7 个版本

0.2.0 2021 年 3 月 14 日
0.1.6 2021 年 3 月 13 日

#1690Rust 模式

24 每月下载量

MIT 许可证

15KB
63

Workflow Status Maintenance

多态常量

一次生成多种类型中的数值常量的宏。

您可以让数字 π 在 f64 或 f32 中可用

该宏的设计考虑了三个目标

  • 在编译时捕获所有溢出错误
  • 最小化代码占用空间
  • 易于阅读和使用

这被视为对 Rust Pre-RFC #1337 一年多的争论的临时解决方案

语法

    use polymorphic_constant::polymorphic_constant;

    polymorphic_constant! {
        const PI: f32 | f64 = 3.141592653589793;
    }

    // Which can then be used as

    fn pi_squared () -> f64 {
        PI.f64 * PI.f64
    }

支持一些特性

    use polymorphic_constant::polymorphic_constant;

    polymorphic_constant! {

        /// Doc comment attributes
        const PI: f32 | f64 = 3.141592653589793;

        // Visibility modifiers (for both constant and type)
        pub (crate) const E: f32 | f64 = 2.7182818284590452;

        // Nonzero numeric types (NonZeroI32, NonZeroU8, etc)
        const ASCII_LINE_RETURN: u8 | nz_u8 = 10;
    }

    // You can handle constants like any const struct
    const PI_COPY: PI = PI;
    const PI_F32: f32 = PI.f32;

    // Into is implemented for every variant of the constant
    fn times_pi<T: std::ops::Mul<T>> (value: T) -> <T as std::ops::Mul>::Output
    where
        PI: Into<T>,
    {
        value * PI.into()
    }

    assert_eq!(times_pi(2.0), 6.283185307179586f64);

安全性

此系统确保您保留 rust 提供的所有安全和警告,但仅此而已

任何不兼容的类型都将阻止编译

  • 如果将浮点字面值转换为无穷大,则无法存储
const FAILS: f32 | f64 =  3141592653589793238462643383279502884197.0;
  • 字面值不能存储在无法容纳它们的类型中
const FAILS: u64 | nz_i8 = 128;
  • 负数不能存储在无符号类型中
const FAILS: i64 | u8 = -1;
  • 0 不能存储在非零类型中
const FAILS: nz_u8 | nz_u16 | nz_u32 = 0;
  • 然而,浮点数可能会丢失精度,而且可能很多
const SUCCEEDS: f32 = 3.141592653589793238462643383279;

警告

目前,同一常量不能同时包含 int 和 float 变体

    const FAIL: i32 = 0.1;
    const FAIL: f32 = 0;

常量必须用无类型字面值初始化

    const FAIL: i32 = 0u32;

上述示例是否危险尚不清楚,因此这是一个保守的选择。

示例

use polymorphic_constant::polymorphic_constant;

polymorphic_constant! {
    const HEIGHT: i8 | u8 | i16 | u16 | i32 | u32 = 16;
    const WIDTH: i8 | u8 | i16 | u16 | i32 | u32 = 32;
}

fn main() {
    let size = HEIGHT.i16 * WIDTH.i16;

    assert_eq!(size, 16 * 32);

    let height_copy:i32 = HEIGHT.into();

    assert_eq!(HEIGHT.i32, height_copy);
}

支持

我非常欢迎对使用方式的任何反馈,以供未来的改进和功能开发。

许可证:MIT

无运行时依赖