当为该类型的引用实现了我需要的所有特征时,如何将类型直接存储在结构中?
How can I store a type directly in a struct when all the traits I need are implemented for references to that type?
Petgraph 实现了其所有特性以引用其内部图形类型。如何在结构中存储和使用 Graph
而不是 &Graph
?
这有效但存储了对图表的引用:
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<G>
where
G: GraphBase,
{
state_network: G,
state: <G as GraphBase>::NodeId,
}
impl<G> StateMachine<G>
where
G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<G as Data>::NodeWeight: Eq + Copy,
<G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <G as Data>::EdgeWeight) -> Option<<G as Data>::NodeWeight> {
for edge in self.state_network.edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match self.state_network.node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <G as Data>::NodeWeight) -> Option<StateMachine<G>> {
for nr in network.node_references() {
if *(network.node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(&sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
但是直接存储Graph是行不通的
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<'a, G>
where
&'a G: GraphBase,
{
state_network: G,
state: <&'a G as GraphBase>::NodeId,
}
impl<'a, G> StateMachine<'a, G>
where
&'a G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<&'a G as Data>::NodeWeight: Eq + Copy,
<&'a G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
for edge in (&self.state_network).edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match (&self.state_network).node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <&'a G as Data>::NodeWeight) -> Option<StateMachine<'a, G>> {
for nr in network.node_references() {
if *((&network).node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
我现在不熟悉 petgraph
及其概念。根据我在结构中存储引用的经验,几乎总是以完全重写结束,所以我的方法应该是这样的:
struct StateMachine<G, E, N>
where
G: GraphBase<EdgeId = E, NodeId = N>,
E: Copy + PartialEq,
N: Copy + PartialEq,
{
state_network: G,
state: N,
}
impl<G, E, N, EW, NW> StateMachine<G, E, N>
where
G: Data<NodeWeight = NW, EdgeWeight = EW>
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase<EdgeId = E, NodeId = N>,
E: Copy + PartialEq,
N: Copy + PartialEq,
for<'a> &'a G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data<NodeWeight = NW, EdgeWeight = EW>
+ GraphBase<EdgeId = E, NodeId = N>,
EW: Eq + Copy,
NW: Eq + Copy,
{
pub fn next<'a, 'b: 'a>(&'a mut self, input: EW) -> Option<NW> {
for edge in (&self.state_network).edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match self.state_network.node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(
network: G,
start: NW,
) -> Option<StateMachine<G, <G as GraphBase>::EdgeId, <G as GraphBase>::NodeId>> {
let mut found = Option::None;
for nr in network.node_references() {
if *(network.node_weight(nr.id())).unwrap() == start {
found = Option::Some(nr.id());
}
}
found.map(|id| StateMachine {
state_network: network,
state: id,
})
}
}
EdgeId
和 NodeId
获取通用参数 (E
,N
),因为这些在 StateMachine
、[=17= 的实现中被重用] 和 EdgeWeight
也得到泛型 (NW
, EW
) 但只加入 &Graph
和 Graph
.
的关联类型
Petgraph 实现了其所有特性以引用其内部图形类型。如何在结构中存储和使用 Graph
而不是 &Graph
?
这有效但存储了对图表的引用:
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<G>
where
G: GraphBase,
{
state_network: G,
state: <G as GraphBase>::NodeId,
}
impl<G> StateMachine<G>
where
G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<G as Data>::NodeWeight: Eq + Copy,
<G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <G as Data>::EdgeWeight) -> Option<<G as Data>::NodeWeight> {
for edge in self.state_network.edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match self.state_network.node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <G as Data>::NodeWeight) -> Option<StateMachine<G>> {
for nr in network.node_references() {
if *(network.node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(&sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
但是直接存储Graph是行不通的
extern crate petgraph;
use crate::petgraph::visit::*;
use petgraph::data::*;
use petgraph::*;
struct StateMachine<'a, G>
where
&'a G: GraphBase,
{
state_network: G,
state: <&'a G as GraphBase>::NodeId,
}
impl<'a, G> StateMachine<'a, G>
where
&'a G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase,
<&'a G as Data>::NodeWeight: Eq + Copy,
<&'a G as Data>::EdgeWeight: Eq + Copy,
{
pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
for edge in (&self.state_network).edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match (&self.state_network).node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(network: G, start: <&'a G as Data>::NodeWeight) -> Option<StateMachine<'a, G>> {
for nr in network.node_references() {
if *((&network).node_weight(nr.id())).unwrap() == start {
return Option::Some(StateMachine {
state_network: network,
state: nr.id(),
});
}
}
return Option::None;
}
}
fn main() {
let mut sn: Graph<&str, u32, petgraph::Directed> = Graph::new();
let sn_item1 = sn.add_node("a");
let sn_item2 = sn.add_node("b");
let sn_item3 = sn.add_node("c");
let sn_item4 = sn.add_node("d");
let sn_item5 = sn.add_node("e");
sn.add_edge(sn_item1, sn_item2, 1);
sn.add_edge(sn_item1, sn_item3, 2);
sn.add_edge(sn_item2, sn_item4, 1);
sn.add_edge(sn_item2, sn_item5, 2);
sn.add_edge(sn_item5, sn_item1, 2);
sn.add_edge(sn_item5, sn_item3, 1);
let mut sm = StateMachine::new(sn, "a").unwrap();
println!("{}", sm.next(1).unwrap());
}
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:29:21
|
29 | for edge in (&self.state_network).edges(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
--> src/main.rs:28:5
|
28 | / pub fn next(&mut self, input: <&'a G as Data>::EdgeWeight) -> Option<<&'a G as Data>::NodeWeight> {
29 | | for edge in (&self.state_network).edges(self.state) {
30 | | if *edge.weight() == input {
31 | | self.state = edge.target();
... |
38 | | return Option::None;
39 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:32:30
|
32 | return match (&self.state_network).node_weight(self.state) {
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
--> src/main.rs:15:6
|
15 | impl<'a, G> StateMachine<'a, G>
| ^^
= note: ...so that the expression is assignable:
expected <&G as petgraph::visit::GraphBase>::NodeId
found <&'a G as petgraph::visit::GraphBase>::NodeId
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
我现在不熟悉 petgraph
及其概念。根据我在结构中存储引用的经验,几乎总是以完全重写结束,所以我的方法应该是这样的:
struct StateMachine<G, E, N>
where
G: GraphBase<EdgeId = E, NodeId = N>,
E: Copy + PartialEq,
N: Copy + PartialEq,
{
state_network: G,
state: N,
}
impl<G, E, N, EW, NW> StateMachine<G, E, N>
where
G: Data<NodeWeight = NW, EdgeWeight = EW>
+ NodeIndexable
+ GraphProp
+ DataMap
+ GraphBase<EdgeId = E, NodeId = N>,
E: Copy + PartialEq,
N: Copy + PartialEq,
for<'a> &'a G: IntoNodeReferences
+ IntoEdgeReferences
+ IntoEdges
+ Data<NodeWeight = NW, EdgeWeight = EW>
+ GraphBase<EdgeId = E, NodeId = N>,
EW: Eq + Copy,
NW: Eq + Copy,
{
pub fn next<'a, 'b: 'a>(&'a mut self, input: EW) -> Option<NW> {
for edge in (&self.state_network).edges(self.state) {
if *edge.weight() == input {
self.state = edge.target();
return match self.state_network.node_weight(self.state) {
Option::Some(weight) => Some(*weight),
Option::None => Option::None,
};
}
}
return Option::None;
}
pub fn new(
network: G,
start: NW,
) -> Option<StateMachine<G, <G as GraphBase>::EdgeId, <G as GraphBase>::NodeId>> {
let mut found = Option::None;
for nr in network.node_references() {
if *(network.node_weight(nr.id())).unwrap() == start {
found = Option::Some(nr.id());
}
}
found.map(|id| StateMachine {
state_network: network,
state: id,
})
}
}
EdgeId
和 NodeId
获取通用参数 (E
,N
),因为这些在 StateMachine
、[=17= 的实现中被重用] 和 EdgeWeight
也得到泛型 (NW
, EW
) 但只加入 &Graph
和 Graph
.