Generics 使用约束泛型的Rust中的函数指针

Generics 使用约束泛型的Rust中的函数指针,generics,rust,Generics,Rust,我正在尝试创建一个如下所示的结构: struct MediaLibrary<B> where B: Ord, { root_dir: PathBuf, item_meta_fn: String, self_meta_fn: String, media_item_filter: fn(&Path) -> bool, media_item_sort_key: fn(&Path) -> B, } struct媒体

我正在尝试创建一个如下所示的结构:

struct MediaLibrary<B>
where
    B: Ord,
{
    root_dir: PathBuf,
    item_meta_fn: String,
    self_meta_fn: String,
    media_item_filter: fn(&Path) -> bool,
    media_item_sort_key: fn(&Path) -> B,
}
struct媒体库
哪里
B:Ord,
{
根目录:PathBuf,
项目\元\ fn:字符串,
self_meta_fn:String,
媒体项过滤器:fn(路径)->bool,
媒体项排序键:fn(&路径)->B,
}
最后两个字段将用作谓词,分别测试给定路径是否为有效的媒体文件和对路径向量进行排序(使用
sort\u by\u key

但是,目前的设计是不灵活的:两个函数都固定为只接受
Path
。我希望能够使用
P:AsRef
,就像stdlib用于其许多文件和路径方法一样,但我不确定如何添加它


我为
MediaLibrary
使用的许多
impl
'd方法已经在使用
p:AsRef
作为它们的参数,所以我的直觉告诉我会有冲突。

据我所知,函数指针不能具有泛型类型,我甚至不认为Rust解析器接受这样的构造

此外,您不能简单地切换到结构上的额外类型参数,因为结构本身将不使用这些参数:

struct MediaLibrary<F, P1, K, P2, B>
where
    F: Fn(P1) -> bool,
    P1: AsRef<Path>,
    K: Fn(P2) -> B,
    P2: AsRef<Path>,
    B: Ord,
{
    root_dir: PathBuf,
    item_meta_fn: String,
    self_meta_fn: String,
    media_item_filter: F,
    media_item_sort_key: K,
}
struct媒体库
哪里
F:Fn(P1)->bool,
P1:AsRef,
K:Fn(P2)->B,
P2:AsRef,
B:Ord,
{
根目录:PathBuf,
项目\元\ fn:字符串,
self_meta_fn:String,
介质项过滤器:F,
媒体项排序键:K,
}
错误[E0392]:从未使用参数'P1'
-->src/main.rs:3:24
|
3 |结构媒体库
|^^未使用的类型参数
|
=帮助:考虑删除“P1”或使用标记,如“STD::标记::幻像数据”
相反,您可以选择仅在使用约束的函数上应用约束:

struct MediaLibrary<F> {
    media_item_filter: F,
}

impl<F> MediaLibrary<F> {
    fn do_filter<P>(&self)
    where
        F: Fn(P) -> bool,
        P: AsRef<Path>,
    {}
}
struct媒体库{
介质项过滤器:F,
}
impl媒体库{
fn do_过滤器

(&self) 哪里 F:Fn(P)->bool, P:AsRef, {} }


正如消息所述,您也可以使用
PhantomData

据我所知,您不能使用泛型类型的函数指针,我甚至认为Rust解析器不接受这样的构造

此外,您不能简单地切换到结构上的额外类型参数,因为结构本身将不使用这些参数:

struct MediaLibrary<F, P1, K, P2, B>
where
    F: Fn(P1) -> bool,
    P1: AsRef<Path>,
    K: Fn(P2) -> B,
    P2: AsRef<Path>,
    B: Ord,
{
    root_dir: PathBuf,
    item_meta_fn: String,
    self_meta_fn: String,
    media_item_filter: F,
    media_item_sort_key: K,
}
struct媒体库
哪里
F:Fn(P1)->bool,
P1:AsRef,
K:Fn(P2)->B,
P2:AsRef,
B:Ord,
{
根目录:PathBuf,
项目\元\ fn:字符串,
self_meta_fn:String,
介质项过滤器:F,
媒体项排序键:K,
}
错误[E0392]:从未使用参数'P1'
-->src/main.rs:3:24
|
3 |结构媒体库
|^^未使用的类型参数
|
=帮助:考虑删除“P1”或使用标记,如“STD::标记::幻像数据”
相反,您可以选择仅在使用约束的函数上应用约束:

struct MediaLibrary<F> {
    media_item_filter: F,
}

impl<F> MediaLibrary<F> {
    fn do_filter<P>(&self)
    where
        F: Fn(P) -> bool,
        P: AsRef<Path>,
    {}
}
struct媒体库{
介质项过滤器:F,
}
impl媒体库{
fn do_过滤器

(&self) 哪里 F:Fn(P)->bool, P:AsRef, {} }


正如消息所述,您也可以使用
PhantomData

为什么它们必须是函数指针而不是闭包?嗨,谢普,没有理由这样做!我不熟悉闭包的类型定义,它们是
Fn
/
FnMut
/
FnOnce
特性吗?没错,函数指针本机实现了这些特性,因此可以在同一位置使用它们。然而,我不确定这两种方法是否真的能解决你的问题。我是否遗漏了一些棘手的问题?似乎我需要一个
where
中的
where
,类似于:
media\u item\u filter:F其中F:Fn(P)->bool;其中P:AsRef
为什么它们必须是函数指针而不是闭包?嗨,谢普,没有理由这样做!我不熟悉闭包的类型定义,它们是
Fn
/
FnMut
/
FnOnce
特性吗?没错,函数指针本机实现了这些特性,因此可以在同一位置使用它们。然而,我不确定这两种方法是否真的能解决你的问题。我是否遗漏了一些棘手的问题?似乎我需要一个
where
中的
where
,类似于:
media\u item\u filter:F其中F:Fn(P)->bool;其中P:AsRef