在结构体内部调用盒装函数时类型不匹配



我试图根据下面的struct Problem描述一种运行"问题"的通用方法。这些结构包括测试输入/输出和求解器函数。我的目标是通过与标准I/O交互来运行这些问题,或者通过一些测试函数来验证solver对给定test_input/test_output的有效性。这里的草图只包括一个测试函数。

当我尝试编译它时,我得到类型不匹配:

problem.rs:43:22: 43:27 error: mismatched types:
 expected `R`,
    found `std::io::cursor::Cursor<&[u8]>`
(expected type parameter,
    found struct `std::io::cursor::Cursor`) [E0308]
problem.rs:43     (problem.solver)(input, &mut output);
                                   ^~~~~
problem.rs:43:22: 43:27 help: run `rustc --explain E0308` to see a detailed explanation
problem.rs:43:29: 43:40 error: mismatched types:
 expected `&mut W`,
    found `&mut std::io::cursor::Cursor<collections::vec::Vec<u8>>`
(expected type parameter,
    found struct `std::io::cursor::Cursor`) [E0308]
problem.rs:43     (problem.solver)(input, &mut output);
                                          ^~~~~~~~~~~
problem.rs:43:29: 43:40 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to 2 previous errors

我期望编译器将Cursor<&[u8]>作为BufRead er, Cursor<Vec<u8>>作为Write r,但它不起作用。我不知道对RW的期望是什么。

我试图通过直接调用求解器来运行一个类似的测试函数,而不涉及Problem,它工作了;所以我想这些错误可能与我调用(problem.solver)(input, &mut output)的方式有关。除了这个,我就不知道了。有人能给我提示一下这里发生了什么吗?

use std::io::prelude::*;
use problems::Problem;
mod problems {
    use std::io::prelude::*;
    pub struct Problem<'a, R, W>
        where R: BufRead, W: Write
    {
        test_input: &'a str,
        test_output: &'a str,
        solver: Box<fn(R, &mut W)>,
    }
    mod a_problem {
        use std::io::prelude::*;
        use super::Problem;
        pub fn getProblem<'a, R, W>() -> Problem<'a, R, W>
            where R: BufRead, W: Write
        {
            Problem {
                test_input: unimplemented!(),
                test_output: unimplemented!(),
                solver: Box::new(solver),
            }
        }
        fn solver<R, W>(input: R, output: &mut W)
            where R: BufRead, W: Write
        {
            unimplemented!();
        }
    }
}
fn test_solver<R, W>(problem: Problem<R, W>)
    where R: BufRead, W: Write
{
    let input = std::io::Cursor::new(problem.test_input.as_bytes());
    let mut output = std::io::Cursor::new(Vec::<u8>::new());
    (problem.solver)(input, &mut output);
    assert_eq!(problem.test_output.as_bytes(), &*output.into_inner());
}
fn main() {
    let problem = problems::a_problem::getProblem();
    test_solver(problem);
}

您定义Problem结构体的方式意味着RWProblem实例化时是固定的。在test_solver中,您允许调用者指定他们想要的任何R和任何W,但随后您尝试将特定的Cursor类型传递给(problem.solver)

您可以通过两种方式修复此问题:

1)不要将test_solver定义为泛型函数。请注意,您不能对RW使用不同的类型多次调用(problem.solver)

fn test_solver<'a>(problem: Problem<'a, std::io::Cursor<&'a [u8]>, std::io::Cursor<Vec<u8>>>)
{
    let input = std::io::Cursor::new(problem.test_input.as_bytes());
    let mut output = std::io::Cursor::new(Vec::<u8>::new());
    (problem.solver)(input, &mut output);
    assert_eq!(problem.test_output.as_bytes(), &*output.into_inner());
}

2)不要将solver字段定义为泛型。让函数接受trait引用。

use std::io::prelude::*;
use problems::Problem;
mod problems {
    use std::io::prelude::*;
    pub struct Problem<'a>
    {
        pub test_input: &'a str,
        pub test_output: &'a str,
        pub solver: Box<fn(&mut BufRead, &mut Write)>,
    }
    pub mod a_problem {
        use std::io::prelude::*;
        use super::Problem;
        pub fn getProblem<'a>() -> Problem<'a>
        {
            Problem {
                test_input: unimplemented!(),
                test_output: unimplemented!(),
                solver: Box::new(solver),
            }
        }
        fn solver(input: &mut BufRead, output: &mut Write)
        {
            unimplemented!();
        }
    }
}
fn test_solver(problem: Problem)
{
    let mut input = std::io::Cursor::new(problem.test_input.as_bytes());
    let mut output = std::io::Cursor::new(Vec::<u8>::new());
    (problem.solver)(&mut input, &mut output);
    assert_eq!(problem.test_output.as_bytes(), &*output.into_inner());
}
fn main() {
    let problem = problems::a_problem::getProblem();
    test_solver(problem);
}

最新更新