在 `cfg` 宏下使用条件编译模块

Using conditionally compiled module under `cfg` macro

我想知道如何在 cfg! 宏下使用条件编译模块。我正在尝试这个:

pub fn f() { ... }

#[cfg(feature = "x")]
pub mod xmodule {
   pub fn f() { ... }
}

pub fn test() {
  if cfg!(feature = "x") {
    xmodule::f();
  } else {
    f();
  }; 
}

当我用 cargo check --features x 编译它时它工作正常,但如果我不启用该功能它会失败并出现以下错误:

use of undeclared type or module `xmodule`

是我做错了什么还是编译不够智能,无法理解如果未设置该功能则不应使用该模块?

虽然 #[cfg] 属性将有条件地编译代码,但 cfg! 给出等效的布尔值(例如,如果启用了某个功能,则为 true,否则为 false)。所以你的代码基本上编译成:

pub fn test() {
  if false { // assuming "x" feature is not set
    xmodule::f();
  } else {
    f();
  }; 
}

因此两个分支都必须仍然包含有效代码,即使只有一个分支 运行。

要获得实际的条件编译,您可以这样做:

pub fn test() {
  #[cfg(feature = "x")]
  fn inner() {
    xmodule::f()
  }

  #[cfg(not(feature = "x"))]
  fn inner() {
    f()
  }

  inner();
}

Playground example

或者您可以使用第三方宏,例如 cfg-if:

use cfg_if::cfg_if;

pub fn test() {
  cfg_if! {
    if #[cfg(feature = "x")] {
      xmodule::f();
    } else {
      f();
    }
  }
}

Playground example