如何将完整类型的部分推断传递给宏?

问题描述 投票:0回答:1

Petgraph 是一个很酷的 Rust 库,用于处理图形。例如。通过标记为 2024 的箭头连接的两个节点

digraph { // Graphviz DOT syntax
    a [ label = "A" ]
    b [ label = "B" ]
    a -> b [ label = "2024" ]
}

将被写成(通过内部通用节点和边类型的 add 方法进行类型推断):

use petgraph::graph::Graph;
let mut graph = Graph::new(); // Graph::<&str, i32>::new();
let a = graph.add_node("A");
let b = graph.add_node("B");
graph.add_edge(a, b, 2024);

现在我想将其(从更大的用例缩小范围)打包到宏中。由于 Petgraph 有各种图的实现,我想参数化确切的类型:

use petgraph::stable_graph::StableGraph;
macro_rules! graph {
    ($type:ty) => {{
        let mut graph = $type::new();
        let a = graph.add_node("A");
        let b = graph.add_node("B");
        graph.add_edge(a, b, 2024);
        graph
    }}
}
let g = graph!(StableGraph);

这个

$type::new()
给出了不以标识符开头的类型需要在限定路径中用尖括号括起来:
<
>
以及我是否这样做添加缺少的通用参数:
<N, E> 

这可行,但失去了内部类型的巧妙推理:

let mut graph = <$type>::new();
…
let g = graph!(StableGraph<&str, i32>);

我也尝试过

$type:path
,但面临着几乎相同的问题。如何使这个宏接受要推断的部分类型以及完整类型?

generics rust macros
1个回答
0
投票

这不是一个确切的答案,因为它不涉及宏,但请考虑使用通用函数。看起来

Build
特质可能比较合适。然后,您可以将部分推断类型与该函数一起使用,例如
graph::<StableGraph<_, _>>()

use petgraph::{data::Build, visit::Data};

fn graph<T>()
where
    T: Build + Data + Default,
    <T as Data>::NodeWeight: From<&'static str>,
    <T as Data>::EdgeWeight: From<u16>,
{
    let mut graph = T::default();
    let a = graph.add_node("A".into());
    let b = graph.add_node("B".into());
    graph.add_edge(a, b, 2024u16.into());
    graph
}
© www.soinside.com 2019 - 2024. All rights reserved.