问题描述
有一个库int set(string key,string value)
{
// Use existing element from map if it exists,// or create a new if it doesn't
container[key].push_back(value);
// The vector is guaranteed to exist at this point,// and contain at least one element
return container[key].size() - 1;
}
,具有功能crate-a
和feature-a
。我想创建一个依赖于feature-b
的新库crate-b
。
二进制crate-a
同时取决于crate-c
和crate-a
并指定crate-b
的功能。
我想根据为crate-a
选择的功能集提供crate-b
函数greet
的不同实现。
crate-a
是否可以通过// at crate-b/src/lib.rs
#[cfg(not(feature = "crate-a/feature-a"))]
pub fn greet() {
println!("General impl");
}
#[cfg(feature = "crate-a/feature-a")]
pub fn greet() {
println!("Feature-A impl");
}
检查crate-a
的功能?
我同时控制crate-b
和crate-a
。甚至应该在crate-b
中进行某些更改的方法也对我有效。
解决方法
我能想到的唯一在编译时实现此目标的方法是根据启用的功能在crate-a
中有条件地定义宏。例如,专门用于指定feature-a
的宏看起来像这样:
// in crate-a/src/lib.rs
#[cfg(feature = "feature-a")]
#[doc(hidden)]
#[macro_export]
macro_rules! __cfg_feature_a {
( $( $tok:tt )* ) => { $( $tok )* }
}
#[cfg(not(feature = "feature-a"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __cfg_feature_a {
( $( $tok:tt )* ) => {}
}
这些宏可由其他包装箱使用,但通过crate-a
从#[doc(hidden)]
的公共API中隐藏了起来,并且根据功能标志而扩展为给定的相同令牌或空主体。然后,您可以像这样在crate-b
中使用它们:
// in crate-b/src/lib.rs
pub fn unconditional_fn() {}
crate_a::__cfg_feature_a! {
pub fn cfg_feature_a_fn() {}
}
这显然是一个非常棘手的解决方案,并且需要为您使用的功能标志的每种组合定义很多样板,但是应该基于crate-a
的功能在编译时条件编译中起作用。
编辑:serde
使用类似于其serde_if_integer128
宏的方法。