rust - 自动将 &String 强制转换为 &str

标签 rust

我正在尝试将一对字符串引用列表转换为属性。它适用于 &str&str其次是 &String (将 Deref 编辑为 &str)或 String.as_ref() .但是当第一个参数是 &String 类型时,编译器错误:

the trait std::convert::AsRef<[(&'static str, &str)]> is not implemented for [(&str, &std::string::String); 1]

如何允许&String强制&str作为第一个参数?

use std::collections::HashMap;

#[derive(Debug)]
pub struct Attributes<'a>(HashMap<&'static str, &'a str>);

impl<'a, T> From<T> for Attributes<'a>
where
    T: AsRef<[(&'static str, &'a str)]>,
{
    fn from(item: T) -> Self {
        Attributes(item.as_ref().into_iter().map(|&(k, v)| (k, v)).collect())
    }
}

fn main() {
    let fruit = "banana".to_string();
    let attr: Attributes = [("fruit", "apple"), ("new_fruit", &fruit)].into(); // This works. As it is coerced into &str because of the first one.
    let another: Attributes = [("fruit", &fruit)].into(); // Does not work as type is &String. Help! Make it work.
    let one_more: Attributes = [("fruit", fruit.as_ref())].into(); // Works
    println!("{:?}", attr);
    println!("{:?}", another);
    println!("{:?}", one_more);
}

Link to Rust Playground

最佳答案

我不认为这会使用 AsRef 起作用因为同一类型可以自由实现这两个 AsRef<[(&str, &str)]>AsRef<[(&str, &String)]> ,这在您使用 AsRef 的任何方面都是模棱两可的.

您可以改为直接实现 From对于您想要支持的那些类型,例如各种大小的数组。

use std::collections::HashMap;

#[derive(Debug)]
pub struct Attributes<'a>(HashMap<&'static str, &'a str>);

macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            impl<'a> From<[(&'static str, &'a str); $N]> for Attributes<'a> {
                fn from(array: [(&'static str, &'a str); $N]) -> Self {
                    Attributes(array.iter().cloned().collect())
                }
            }

            impl<'a> From<[(&'static str, &'a String); $N]> for Attributes<'a> {
                fn from(array: [(&'static str, &'a String); $N]) -> Self {
                    Attributes(array.iter().map(|&(k, v)| (k, v.as_ref())).collect())
                }
            }
        )*
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

fn main() {
    let fruit = "banana".to_string();

    // From<[(&str, &str); 2]>
    let attr: Attributes = [("fruit", "apple"), ("new_fruit", &fruit)].into();
    println!("{:?}", attr);

    // From<[(&str, &String); 1]>
    let another: Attributes = [("fruit", &fruit)].into();
    println!("{:?}", another);
}

关于rust - 自动将 &String 强制转换为 &str,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48970275/

相关文章:

rust - 是否可以为另一个项目中的库定义一个数组长度常量?

oop - Rust 特征对象的 &self 不能在特征默认函数中使用

error-handling - 为什么 Rust 的 usize 到 u128 转换被认为是失败的?

rust - Rust 中的一个可变借用或多个不可变借用……为什么?

data-structures - "overflow while adding drop-check rules"实现手指树时

rust - 为什么在编译动态库后不使用 -C prefer-dynamic 标志动态链接 Rust libstd?

rust - 如何声明一个采用三种不同泛型类型并返回两个较大数字的平方和的函数?

rust - 迭代器表示任意行为

json - "Unknown deriving trait ToJson";什么使特征可推导?

rust - 如何在 gtk-rs 闭包中设置变量?