我正在尝试创建一个简单的实用程序函数,从中读取多个元素stdin并将它们放入集合中并返回它.但是我在这一点上陷入困境.编译说missing associated type Err value.如何使其工作,同时尽可能保持通用?
虽然这个功能似乎没用,但它用于学习语言及其类型系统.
use std::io::{ stdin };
use std::str::FromStr;
use std::io::Read;
use std::iter::FromIterator;
pub fn read_all<C>() -> C
where C: FromIterator<FromStr<Err>>
{
let mut buff = String::new();
stdin().read_to_string(&mut buff).expect("read_to_string error");
buff.split_whitespace()
.filter_map(|w| w.parse().ok())
.collect()
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
let v: Vec<i32> = read_all();
Run Code Online (Sandbox Code Playgroud)
为了使其编译,您需要更改为代码的唯一方法是函数的类型签名:
pub fn read_all<C, F>() -> C
where F: FromStr,
C: FromIterator<F>
Run Code Online (Sandbox Code Playgroud)
你的代码几乎是正确的,但有一个问题:
FromIterator<T>是一种特质,但是T一种类型.FromStr的地方T,但是FromStr一个特点,而不是一种类型.要解决这个问题,您需要获得一个实现的类型FromStr.您可以通过向F函数添加类型参数并使用约束来执行此操作where F: FromStr.然后你就可以写了FromIterator<F>.
除了使用特征而不是类型的问题,键入FromStr<Err>是错误的语法.而在这种情况下,没有必要指定类型Err的FromStr特质,你能做到这一点,如下图所示:
pub fn read_all<C, F, E>() -> C
where F: FromStr<Err=E>,
C: FromIterator<F>
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,FromStr<E>我们需要写作而不是写作FromStr<Err=E>.也就是说,您需要显式键入要引用的关联类型的名称.
通常,特征不能被视为类型.但是,此规则有例外情况,如下例所示:
use std::fmt::Display;
pub fn print_box(thing: Box<Display>) {
println!("{}", thing)
}
fn main() { print_box(Box::new(42)); }
Run Code Online (Sandbox Code Playgroud)
在这里,你会期望T在Box<T>是一个类型,但Display性状,而不是供应.但是,编译器不会拒绝该程序.类型检查器Display视为未大小的类型.也就是说,在编译时具有未知大小的对象的类型(因为它可以是任何类型的实现Display).当Tin Box<T>是特征时,结果类型通常被称为特征对象.这里不可能深入讨论这个主题,但是我想提到的链接是一个很好的起点,以防你想了解更多.
| 归档时间: |
|
| 查看次数: |
1870 次 |
| 最近记录: |