代码之家  ›  专栏  ›  技术社区  ›  lovesh

DRY用于Rust条件编译,具有功能

  •  0
  • lovesh  · 技术社区  · 4 年前

    我的图书馆有几个功能,比如 F1 , F2 , F3 , F4 ,.. 并且一次只能有一个处于活动状态。这些特征进一步分为类型 A , B , C 例如,功能 一层楼 地上二层 类型 A. , F3 , F4 类型 B 等等。

    我(在库中)有几次这样的代码

    #[cfg(any(feature = "F1", feature = "F2"))]
    fn do_onething_for_type_A(... ) {
    
    // repeating same cfg predicate as above
    #[cfg(any(feature = "F1", feature = "F2"))]
    fn do_another_thing_for_type_A(... ) {
    
    #[cfg(any(feature = "F3", feature = "F4"))]
    fn do_onething_for_type_B(... ) {
    

    有办法写上面的吗 cfg 谓词简洁明了,这样我就不必在 #[cfg(any(.. 每次我有这种情况?冗长并不是唯一的问题。每次我介绍一个新功能时,说 F5 例如, A. ,我必须更新行的出现次数 #[cfg(any(feature = "F1", feature = "F2"))] #[cfg(any(feature = "F1", feature = "F2", feature = "F5"))] .

    我的第一个想法是 创造 基于特征的属性,然后使用下面的属性,但似乎我不能这样做。

    #[cfg(any(feature = "F1", feature = "F2"), typeA)]
    #[cfg(any(feature = "F3", feature = "F4"), typeB)]
    
    #[typeA]
    fn do_onething_for_type_A(... ) {...}
    
    #[typeA]
    fn do_another_thing_for_type_A(... ) {
    
    #[typeB]
    fn do_onething_for_type_B(... ) {
    

    为类型声明新特性 A. , B , C 这是我最后的手段。

    0 回复  |  直到 4 年前
        1
  •  4
  •   Alice Ryhl    4 年前

    你可以用 cfg_aliases crate,尽管它需要添加构建脚本。

    // Cargo.toml
    [build-dependencies]
    cfg_aliases = "0.1.0"
    
    // build.rs
    use cfg_aliases::cfg_aliases;
    
    fn main() {
        // Setup cfg aliases
        cfg_aliases! {
            type_a: { any(feature = "F1", feature = "F2") },
            type_b: { any(feature = "F3", feature = "F4") },
            type_c: { feature = "F5" },
        }
    }
    
    #[cfg(type_a)]
    fn do_onething_for_type_A(... ) {...}
    
    #[cfg(type_a)]
    fn do_another_thing_for_type_A(... ) {
    
    #[cfg(type_b)]
    fn do_onething_for_type_B(... ) {
    

    或者,您可以定义宏 like Tokio does .

    macro_rules! cfg_type_a {
        ($($item:item)*) => {
            $(
                #[cfg(any(feature = "F1", feature = "F2"))]
                $item
            )*
        }
    }
    
    cfg_type_a! {
        fn do_onething_for_type_A() {
            ...
        }
    }
    cfg_type_b! {
        fn do_onething_for_type_B() {
            ...
        }
    }
    

    请注意,基于宏的方法可能会给使用CLion IDE的库的任何用户带来麻烦。使用该IDE时,您必须启用

    设置>语言和;框架>锈蚀>展开声明性宏:使用实验引擎

    为上述宏后面定义的东西实现类型补全。