rust 结构初始化需要有序向量

ruyhziif  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(100)

我有一个struct:

pub struct OneDLookup <T: PartialOrd + Sub + Add + Copy + Clone, U: Add + Sub + Copy + Clone>{
    breakpoints: Vec<T>,
    values: Vec<U>,
    last_diff_bp: f64,      //ignore these, they are not important to this question
    last_diff_values: f64,
    first_diff_bp: f64,
    first_diff_values: f64,
}

字符串
这将作为一个查找表,但是有两个重要的事情必须是正确的这个结构:
断点必须按升序排列,例如1、5、7、9,而不是任何其他顺序。断点和值必须具有相同的长度。
有没有可能在编译时(或者在编写时使用rust-analyzer更好)在宏中检查这些?恐怕不是。
我对生 rust 还是个新手,所以我还在学习细节。
我尝试基于vec!()宏创建一个不起作用的小宏,看看我是否能理解那里做了什么,但不幸的是我不知道:

macro_rules! create_1d_lookup {
    (($($bps:expr,)*); ($($vals:expr,)*)) => (
        $crate::my_crate::OneDLookup::new(vec![$($bps),+], vec![$($vals),+])
    );
}


OneDLookup::new()将断点和值向量作为参数。
此结构是常量,初始化后不会改变。

7tofc5zh

7tofc5zh1#

您可以通过创建一个const来实现这一点,该const运行一些逻辑来验证不变量是否被维护,如果不变量被破坏,则会出现异常。死机将被转换为编译失败:

macro_rules! create_1d_lookup {
    (($($bps:expr,)*); ($($vals:expr,)*)) => {{
        const _: () = {
            let breakpoints = [ $($bps,)* ];
            if breakpoints.len() != [ $($vals,)* ].len() {
                // There are multiple ways to count in macros,
                // this is the simplest assuming the expressions are side-effect-free.
                panic!("sizes of vectors don't match");
            }

            let mut i = 1;
            // Can't use a `for` loop in consts currently.
            while i < breakpoints.len() {
                if breakpoints[i - 1] > breakpoints[i] {
                    panic!("breakpoints aren't sorted");
                }
                i += 1;
            }
        };
        $crate::my_crate::OneDLookup::new(vec![$($bps),+], vec![$($vals),+])
    }};
}

字符串
不幸的是,这是一个单体化后的错误,这意味着它不会出现在cargo check中,只会出现在cargo build中。

相关问题