eml*_*lai 4 generics enums type-conversion rust
我有类似以下代码:
enum Value {
Bool(bool),
Int(i32),
Float(f32),
Str(String),
}
fn get_value(key: &str) -> Value {
// read value from file
match key {
"b" => Value::Bool(true),
"i" => Value::Int(666),
"f" => Value::Float(42.),
"s" => Value::Str("".to_string()),
_ => panic!("Key {} not found.", str),
}
}
fn convert<T>(e: &Value) -> T {
// what to put here?
}
fn query<T>(t: &str) -> T {
// … validation etc.
convert::<T>(&get_value(t))
}
fn main() {
let i = query::<i32>("i");
}
Run Code Online (Sandbox Code Playgroud)
即我需要query来自文本文件的一些值.query获取类型参数和字符串键参数.然后它返回与文本文件中该键相关联的值(如果类型参数和值的类型不匹配,则简单panic!).Value并且get_value来自实际代码中的库.
不过我想,当面临一个问题convert一个Value实例,其持有的类型.如果我尝试用简单的方法来做match,我会得到
错误:类型不匹配:预期
T,找到x
其中x一个是bool/ i32/ f32/ String.
在Rust中这样做的正确方法是什么?
这里有一个可能的解决方案:
enum Value {
Bool(bool),
Int(i32),
Float(f32),
Str(String),
}
fn get_value(key: &str) -> Value {
// read value from file
match key {
"b" => Value::Bool(true),
"i" => Value::Int(666),
"f" => Value::Float(42.),
"s" => Value::Str("".to_string()),
_ => panic!("Key {} not found.", key),
}
}
trait ConversionTrait {
type Output;
fn convert(v: &Value) -> Option<Self::Output> {
None
}
}
impl ConversionTrait for i32 {
type Output = i32;
fn convert(v: &Value) -> Option<Self::Output> {
match (*v) {
Value::Int(x) => Some(x),
_ => None
}
}
}
fn convert<T>(e: &Value) -> Option<T> where T : ConversionTrait<Output = T> {
T::convert(e)
}
fn query<T>(t: &str) -> Option<T> where T : ConversionTrait<Output = T> {
// … validation etc.
convert::<T>(&get_value(t))
}
fn main() {
let i = query::<i32>("i");
// let j = query::<f32>("i"); ConversionTrait not implemented
println!("{:?}", i);
}
Run Code Online (Sandbox Code Playgroud)
首先把convert和query方法可能会失败,所以它的更好,他们返回Option它可以None在发生故障的情况下.
其次,在Rust中,目前没有通用的特殊化,因此可能的解决方案是定义一个特征来进行转换,然后仅为您想要转换的类型实现特征.(使用通用专业化,您将实现不同版本的转换功能)
ConversionTrait上述的每个实现都应该从Value对象中提取适当的值并将其返回.我只实现了该i32版本以供参考.