当使用泛型和函数指针克隆结构时,如何修复“方法‘clone’存在,但不满足以下特征边界”?

Qur*_*erd 6 pointers clone function rust

我正在编写一个函数,它将在终端中创建一个菜单界面。要使用该函数,需要传递一个Vec<menu_option>

#[derive(Clone)]
pub struct menu_option<'a, T> {
    pub command: &'a str,
    pub description: &'a str,
    pub action: menu_option_action<'a, T>,
}

#[derive(Clone)]
pub enum menu_option_action<'a, T> {
    sub_menu(Vec<menu_option<'a, T>>),
    callback(fn(state: T) -> T),
    leave,
}
Run Code Online (Sandbox Code Playgroud)

当我设计菜单时,它可以有多个级别,并且可以有重复menu_action。即每一层都有一个“离开”/“返回”:

// In my actual code I construct a vector of `menu_option`s
fn example() {
    type StateType = i32;
    let mut state: StateType = 88;
    let leave_option: menu_option<&mut StateType> = menu_option::<&mut StateType> {
        command: "l",
        description: "leave",
        action: menu_option_action::leave,
    };

    let a = leave_option.clone();
}
Run Code Online (Sandbox Code Playgroud)
#[derive(Clone)]
pub struct menu_option<'a, T> {
    pub command: &'a str,
    pub description: &'a str,
    pub action: menu_option_action<'a, T>,
}

#[derive(Clone)]
pub enum menu_option_action<'a, T> {
    sub_menu(Vec<menu_option<'a, T>>),
    callback(fn(state: T) -> T),
    leave,
}
Run Code Online (Sandbox Code Playgroud)

我该如何解决?

我尝试在网上搜索,但找不到解决方案,至少没有一个对我有用的解决方案(我认为我发现的是旧的 Rust)

我不知道是什么阻止了克隆,因为该T类型的唯一用途是我认为可以克隆的函数指针。

小智 3

当您在&Clone上实现自己时,它会起作用。默认情况下,由于您的结构/枚举具有类型参数,因此该属性的宏扩展会将您的类型的克隆实现限制为.menu_optionmenu_option_action#[derive(Clone)]T: Clone

就您而言,不仅不需要此要求,而且也不太可能得到尊重(例如&mut T不实现Clone)。通过手动实现Clone,您可以摆脱该T: Clone要求并且它可以工作!

请注意,函数指针实现了Copy它的工作原理menu_option_action::callback(*f)

type StateType = i32;

pub struct menu_option<'a, T> {
    pub command: &'a str,
    pub description: &'a str,
    pub action: menu_option_action<'a, T>,
}

impl<'a, T> Clone for menu_option<'a, T> {
    fn clone(&self) -> Self {
        menu_option {
            command: self.command.clone(),
            description: self.description.clone(),
            action: self.action.clone(),
        }
    }
}

pub enum menu_option_action<'a, T> {
    sub_menu(Vec<menu_option<'a, T>>),
    callback(fn(T) -> T),
    leave,
}

impl<'a, T> Clone for menu_option_action<'a, T> {
    fn clone(&self) -> Self {
        match self {
            menu_option_action::sub_menu(sub) => menu_option_action::sub_menu(sub.to_vec()),
            menu_option_action::callback(f) => menu_option_action::callback(*f),
            menu_option_action::leave => menu_option_action::leave,
        }
    }
}

fn main() {
    let mut state: StateType = 88;
    let leave_option: menu_option<&mut StateType> = menu_option {
        command: "l",
        description: "leave",
        action: menu_option_action::leave,
    };

    let a = leave_option.clone();
}
Run Code Online (Sandbox Code Playgroud)