如何仅将某些结构成员设置为其默认值?

How can I set only some struct members to their default values?

我有结构 B:

struct A {}

struct B {
    a: A,
    b: u32,
    c: i8,
    z: usize,
}

A 没有 Default 实现,也没有有意义的默认值。字段 b..z 都需要初始化为默认值(在本例中为 0),并且 A 将被初始化为某个运行时值:

let b = B {
    a: some_a(),
    b: 0,
    c: 0,
    z: 0,
};

这并不理想。

更糟糕的是,如果要将 aa 添加到结构中,则需要将另一个成员添加到初始化程序中。使用 ..Default::default() 不起作用,因为 B 没有 Default 实现,因为默认值中的任何 A 都太昂贵而无法计算,以至于事后简单地丢弃.此外,无论如何,我都需要在 Default 实现中使用一个非常长的结构初始化器。

有没有什么方法可以将剩余的结构成员设置为它们的默认值(这样 b 将设置为默认值 u32)而不用写出所有成员名称?

最好在添加新成员时对结构初始化程序进行最少的更改。这意味着这并不理想:

let b = B {
    a: some_a(),
    b: Default::default(),
    c: Default::default(),
    z: Default::default(),
};

如果您有大型结构,可以通过派生构建器或构造函数让您的生活更轻松。有几个板条箱可以做到这一点,一个流行的是 derive_builder.

使用那个箱子,你可以做类似的事情:

use derive_builder::Builder;

// this derive will generate a struct called BBuilder
#[derive(Builder)]
struct B {
    a: A,
    #[builder(default = "0")]
    b: u32,
    #[builder(default = "0")]
    c: i8,
    /* ... */
    #[default(default = "0")]
    z: usize
}


fn main() {
    let a = A { ... };

    // all default values for fields b..z
    let b = BBuilder::default().a(a).build().unwrap();

    // or specify just some of the fields
    let b = BBuilder::default()
        .a(a)
        .c(42)
        .z(255)
        .build()
        .unwrap();
}

B 添加新字段不会影响使用 BBuilder 的代码,只要这些字段具有默认值即可。缺点是如果您错过必填字段而不是编译错误,您会遇到运行时恐慌。


另一个crate是derive-new,比较简单。你会像这样使用它:

use derive_new::new;

#[derive(new)]
struct B {
    a: A,
    #[new(default)] 
    b: u32,
    #[new(default)] 
    c: i8,
    /* ... */
    #[new(default)]
    z: usize
}

fn main() {
    let a = A { ... };

    // all default values for fields b..z
    let b = B::new(a);

    // To specify some of the default fields, you need to mutate
    let mut b = B::new(a);
    b.c = 42;
    b.z = 255;
}

这不会生成任何额外的结构,它只是添加了一个 new 方法,该方法接受所有非默认参数。如果您遗漏了任何非默认字段,则会出现编译错误。