【发布时间】:2018-12-03 14:10:12
【问题描述】:
我正在学习 Rust 来自 C++ 背景,我正在编写拓扑排序。
输入是一个类型为Map<Key, Set<Key>> 的依赖映射,其中每个节点(键)都映射到它的依赖(一组键)。 Map 和 Set 可以是任何 Map 和 Set 实现。输出是一个具有排序拓扑顺序的向量。
在 C++ 中,我会为 Map 和 Set 使用“模板模板参数”:
template<
class K,
template<class...> class Map,
template<class...> class Set
>
std::vector<K>
topological_sort(Map<K, Set<K>> const &depmap);
此功能可应用于map<Key, set<Key>>或unordered_map<Key, set<Key>>或map<Key, unordered_set<Key>>等
在 Rust 中,似乎没有“模板模板参数”。我可以写如下:
fn topological_sort<K: Eq + Ord + Hash + Clone>(depmp: &BTreeMap<K, HashSet<K>>) -> Option<Vec<K>> {
}
但是代码在容器选择方面不是通用的,因为它不适用于 HashMap<K, HashSet<K>> 等。
我尝试了假设的语法:
fn topological_sort<Map, Set, K: Eq + Ord + Hash + Clone>(depmp: &Map::<K, Set::<K>>) -> Option<Vec<K>>
这不起作用。 Rust 对泛型容器的解决方案是什么?
【问题讨论】:
-
这个特性也被称为 higher kinded types,Rust 还没有。此外,与 C++ 相比,在 Rust 中,您只能访问由 trait bound 提供的泛型类型参数上的方法和关联类型。 Rust 标准库中没有描述通用映射的特征,因此您必须定义自己的特征并为键类型使用关联类型。
-
看看 Rust 中的迭代器。
-
您可能可以使用
M: Index<K, Output=HashSet<K>>之类的东西抽象地图类型,但我认为没有抽象集合类型的等价物。 -
虽然你可以在
HashSet和BTreeSet之间写出你自己的特征来抽象…… -
@SvenMarnach 所以我需要写
trait GenericSet<K>和trait GenericMap<K, V>,然后是impl<K> GenericSet<K> for HashSet<K>,等等。这很有道理,谢谢。