2016-11-21 31 views
1

我想創建一個特徵爲有向圖結構,並提供一個非常基本實現The,但我遇到了編譯器錯誤:「預期的類型參數,發現結構」實現的時候特質

pub trait DiGraph<'a> { 
    type N; 
    fn nodes<T>(&'a self) -> T where T: Iterator<Item=&'a Self::N>; 
    fn pre<T>(&'a self, node: Self::N) -> T where T: Iterator<Item=&'a Self::N>; 
    fn succ<T>(&'a self, node: Self::N) -> T where T: Iterator<Item=&'a Self::N>; 
} 

struct SimpleNode { 
    pre: Vec<usize>, 
    succ: Vec<usize>, 
} 

pub struct SimpleDiGraph { 
    pub nodes: Vec<SimpleNode> 
} 

impl<'a> DiGraph<'a> for SimpleDiGraph { 
    type N = usize; 

    fn nodes<T=std::ops::Range<usize>>(&'a self) -> T { 
     return std::ops::Range { start: 0, end: self.nodes.len() }; 
    } 
    fn pre<T=std::slice::Iter<'a,usize>>(&'a self, node: usize) -> T { 
     return self.nodes[node].pre.iter(); 
    } 
    fn succ<T=std::slice::Iter<'a,usize>>(&'a self, node: usize) -> T { 
     return self.nodes[node].succ.iter(); 
    } 
} 

錯誤消息是:

error[E0308]: mismatched types 
--> digraph.rs:21:16 
| 
21 |   return std::ops::Range { start: 0, end: self.nodes.len() }; 
|    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::ops::Range` 
| 
= note: expected type `T` 
= note: found type `std::ops::Range<usize>` 

error[E0308]: mismatched types 
--> digraph.rs:24:16 
| 
24 |   return self.nodes[node].pre.iter(); 
|    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::slice::Iter` 
| 
= note: expected type `T` 
= note: found type `std::slice::Iter<'_, usize>` 

error[E0308]: mismatched types 
--> digraph.rs:27:16 
| 
27 |   return self.nodes[node].succ.iter(); 
|    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::slice::Iter` 
| 
= note: expected type `T` 
= note: found type `std::slice::Iter<'_, usize>` 

錯誤信息有點令我困惑 - 爲什麼會預期類型參數作爲返回值?這僅僅是一種類型不匹配(例如由於生命期)與誤導性的錯誤信息?

回答

7

<T=std::ops::Range<usize>>不強制Tstd::ops::Range<usize>,它只是導致它默認爲,如果它不知道還有什麼用。

如果您只想返回Range<usize>,則使用Range<usize>作爲返回類型;根本沒有理由擁有通用參數。什麼是你的代碼是現在實際上是說這樣的事情:

  • 「你可以選擇任何你想要的返回類型。如果你不介意,我會返回一個range<usize>」。 「
  • 」我想請你退回String。「
  • TOUGH你會得到一個range<usize>!」
  • 「......但你說......」
  • 我撒謊了!MUAHAHAHAHAHA!

如果實際上所需號碼選擇返回類型,那麼你需要準備返回任意T ......這幾乎是不可能的,因爲它可能是從()String到OpenGL渲染上下文的任何東西。

這樣的話,實際上想要做的就是約束T對一些需要類型實現某種構造函數的特性。 Default就是一個例子。

編輯:只是爲了澄清倍加:不要挑在泛型參數使用的類型,你主叫一樣。

直到現在我才注意到你在特質和實現中使用了不同的定義(不這樣做)。我假設你真的真的試圖做的是說「這種方法返回東西這可用作Iterator,但每個impl可以選擇一個不同的類型。」你不能與泛型做到這一點。

什麼你是性狀相關的類型,像這樣:

pub trait DiGraph<'a> { 
    type Nodes; 
    fn nodes(&'a self) -> Self::Nodes; 
} 

pub struct SimpleNode { 
    pre: Vec<usize>, 
    succ: Vec<usize>, 
} 

pub struct SimpleDiGraph { 
    pub nodes: Vec<SimpleNode> 
} 

impl<'a> DiGraph<'a> for SimpleDiGraph { 
    type Nodes = std::ops::Range<usize>; 

    fn nodes(&'a self) -> Self::Nodes { 
     return std::ops::Range { start: 0, end: self.nodes.len() }; 
    } 
} 
+0

謝謝,很好的解釋,你猜到了我的正確打算。但是,在你的情況下,節點可以是任何東西,這意味着任何在DiGraphs上運行的函數都不會做太多的工作,因爲它不能對節點做出任何假設。所以我想要做的是限制Nodes獲取N的迭代器(在我的例子中使用,但由調用者定義)。我很高興SimpleDiGraph始終返回範圍對象,但實現DiGraph的其他結構應該能夠通過N返回其他迭代器。有什麼方法可以實現這一目標? –

+0

認爲我想通了,似乎你實際上可以限制特徵類型,例如 _type NodeIterator:Iterator ; _ 應該這樣做。現在只需要弄清楚生命期問題。 –

相關問題