将类型关联函数作为参数传递

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

我有一个类型

Network
的实现以及相关函数
pub fn is_acyclic(&mut self) -> bool
。我正在尝试创建一个通用函数
fn run_test(n: usize, f: fn()->bool)
,这样我就可以传递与
Network::is_acyclic
相同签名的函数,这样我就可以将这些函数应用于构造的
Network
s
n
次。请参阅下面的代码块。

#[test]
fn acyclic() {
    assert!(run_test(10, Network::is_acyclic))
}
...
fn run_test(n: usize, f: fn()->bool) -> bool {
    let mut results = vec![];
    for _ in 0..n {
        let (l,r) = gen_test_nets();
        let mut net = Network::new_random(l, r);
        results.push(net.f());
    }
    results.iter().all(|&x| x)
}

我特别遇到两个错误:

Mismatched Types ...
   = note: expected fn pointer 'fn(Network<_>) -> _'
                 found fn item 'for<'a> fn(&'a mut Network<Node<_>>) -> _ {Network::<Node<_>>::is_acyclic}'

我收集到的信息意味着我在

Network::is_acyclic
方法中传递了
acyclic
错误。我尝试过以
Network::is_acyclic()
的身份传递,我尝试过以各种形式尝试过
Try
as
,我在网上找到了类似的问题,老实说我不明白我在做什么。我还尝试了
where
定义上的
run_test
关键字,我认为它应该将参数类型强制转换为函数,尽管我不认为这是问题,因为它知道我正在尝试将函数指针作为参数(这就是我相信我想要的)。

我也尝试过这个版本的

run_test
方法,结果相同

fn run_test<T>(n: usize, f: fn(Network<T>)->bool) -> bool {
    let mut results = vec![];
    for _ in 0..n {
        let (l,r) = gen_test_nets();
        let mut net = Network::new_random(l, r);
        results.push(net.f());
    }
    results.iter().all(|&x| x)
}

特别是,

is_acyclic
是在
impl<T: Clone + PartialEq + Eq + Hash> Network<Node<T>>
中实现的,我尝试在测试方法中进行所有这些声明,但没有成功。我得到了相同的错误“预期的函数指针,找到的函数项”以及一些类似于
associated type bindings are not allowed here... assert!(run_test::<T: Clone + PartialEq + Eq + Hash>(10, Network::is_acyclic))
的额外错误。

我遇到的另一个错误是

no method named 'f' found for struct 'Network' in the current scope
中的
results.push(net.f());
行上的
run_test
。我不确定一旦我在该方法中正确传递函数指针为
f
后,此错误是否会自行解决。

function rust parameter-passing
1个回答
0
投票

is_acyclic
不是一个“关联函数”,它是一个方法。这意味着它以某种方式采用
self
参数。在你的例子中,由于它是
Network<Node<T>>
的特征实现的一部分,它的原型相当于:

fn is_acyclic (self: &Network<Node<T>>) -> bool;

给定一个类型为

net
的实例
Network<Node<T>>
,通常使用方法调用语法
net.is_acyclic()
来调用它,但也可以使用统一函数调用语法:
Network::<Node::<T>>::is_acyclic (&net)
来调用它。所以在你的情况下,这应该有效:

#[test]
fn acyclic() {
    // Need to replace the `?????` with the real type that `gen_test_nets`
    // and `Network::new_random` create.
    assert!(run_test(10, Network::<Node::<?????>>::is_acyclic))
}
...
fn run_test(n: usize, f: &Network<Node<?????>>) -> bool {
    let mut results = vec![];
    for _ in 0..n {
        let (l,r) = gen_test_nets();
        // You can find out the real type of `net` with an IDE or:
        // let net: () = Network::new_random(l, r);
        // which will fail to compile and the error message will give
        // you the actual type.
        let mut net = Network::new_random(l, r);
        results.push(f (&net));
    }
    results.iter().all(|&x| x)
}
© www.soinside.com 2019 - 2024. All rights reserved.