【问题标题】:Why is impl not in scope为什么 impl 不在范围内
【发布时间】:2018-08-18 15:14:02
【问题描述】:

我是 Rust 新手,在我的学习玩具项目中,我需要一个带有可变节点的图形数据结构,所以我想出了:

use std::cell::RefCell;
use std::clone::Clone;
use std::cmp::Eq;
use std::collections::HashMap;
use std::hash::Hash;
use std::rc::Rc;

pub trait Constructible<T> {
    type C;
    fn new(Self::C) -> T;
}

#[derive(Debug)]
pub struct HashedGraph<K: Eq + Hash + Clone, T: Constructible<T>> {
    graph: HashMap<K, Rc<RefCell<T>>>,
}

impl<K, T> HashedGraph<K, T>
where
    K: Eq + Hash + Clone,
    T: Constructible<T>,
{
    pub fn new<C>(connections: HashMap<K, C>) -> HashedGraph<K, T> {
        let mut graph: HashMap<K, Rc<RefCell<T>>> = HashMap::new();

        for key in connections.keys() {
            graph.insert(
                key.clone(),
                Rc::new(RefCell::new(C::new(*connections.get(key).unwrap()))),
            );
        }

        HashedGraph { graph }
    }
}

impl Constructible<String> for String {
    type C = String;
    fn new(instring: String) -> String {
        instring
    }
}

fn main() {
    let mut test = HashMap::new();
    test.insert("one", "ONE");
    test.insert("two", "TWO");
    let hg = HashedGraph::new(test);
}

我的想法是,我希望节点可以从另一种数据类型构造,但该数据不包含在 Graph 中,因此是关联类型而不是泛型参数。节点 T 稍后将包含连接,它们只是指向其他节点的弱指针,但对于这个问题,这并不真正相关。编译时出现错误:

error[E0599]: no function or associated item named `new` found for type `C` in the current scope
  --> src/main.rs:26:61
   |
26 |             graph.insert(key.clone(), Rc::new(RefCell::new( C::new( *connections.get(key).unwrap() ))));
   |                                                             ^^^^^^ function or associated item not found in `C`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `new`, perhaps you need to implement it:
           candidate #1: `Constructible`

我不明白为什么constructible 的实现不在范围内或者还有什么不正确的。如果这是一种不习惯的实现方式,我会很高兴收到建议!

【问题讨论】:

  • C 中的 new&lt;C&gt; 没有任何内容将其限制为 Constructable。另外我认为您可以只使用Into/From 而不是引入新特征,因为它看起来像转换。
  • 另外,实现String 可能不是您的意思,因为您在主函数中使用了&amp;str
  • 为什么Constructible 需要关联类型?类型参数T 在您使用它的方式上似乎是多余的,可以只是Self

标签: generics rust associated-types


【解决方案1】:

new&lt;C&gt;()的声明中,类型参数C是一个没有约束的新类型变量。您似乎打算将它作为来自 TConstructible 实例的关联类型,您可以这样表达:

pub fn new(connections: HashMap<K, T::C>) -> HashedGraph<K, T> {
 ...
}

您的代码还有许多其他问题:

  • 您正在使用&amp;str 实例化对象,但您只为String 添加了Constructible 实例。这些是不同的类型。
  • 您不需要使用hashmap.get(key) 来访问该值。您可以只使用iter() - 或者在这种情况下使用drain(),因为无论如何您都将所有值从一个容器移动到另一个容器,因此如果您不需要原始的HashMap,这将避免借用问题。
  • Constructible 的类型参数是多余的。这始终是Self
  • fn new() -&gt; T 中推断T 的唯一方法是调用者选择使用它的位置。理论上,Constructible 的另一个实现可能具有相同的关联C 类型,所以这还不够。这意味着在构造 HashedGraph 时需要类型注释。

Here's a version of your code 可以编译,尽管我对您真正想要实现的目标做了一些假设。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-01
    相关资源
    最近更新 更多