在结构中调用Boxed函数时键入不匹配

时间:2015-10-24 15:21:08

标签: types rust type-mismatch

我尝试绘制一个运行“问题”的通用方法,根据下面的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,将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);
}

1 个答案:

答案 0 :(得分:4)

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

您可以通过两种方式解决此问题:

1)不要将test_solver定义为通用函数。请注意,对于(problem.solver)R的不同类型,您不能多次拨打W

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字段定义为通用字段。让函数采用特征引用。

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);
}