从泛型方法中的union-style枚举中获取活动值

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中这样做的正确方法是什么?

eul*_*isk 6

这里有一个可能的解决方案:

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)

首先把convertquery方法可能会失败,所以它的更好,他们返回Option它可以None在发生故障的情况下.

其次,在Rust中,目前没有通用的特殊化,因此可能的解决方案是定义一个特征来进行转换,然后仅为您想要转换的类型实现特征.(使用通用专业化,您将实现不同版本的转换功能)

ConversionTrait上述的每个实现都应该从Value对象中提取适当的值并将其返回.我只实现了该i32版本以供参考.

  • 虽然,实现`i32`的特性并且具有i32的相关类型似乎是多余的 - 我认为你不想要相关的类型. (3认同)