如何使用普通的struct构造函数创建具有关联类型的值?

时间:2018-03-23 12:00:31

标签: rust

我正在尝试使用结构T P::Child中的P创建一个初始化结构P: Parent<Child = T>的宏。

macro_rules! init {
    ($t:tt, { $( $k:ident =>  $v:expr ),* }) => {
        <$t as Parent>::Child {
            $( $k: $v ),*
        }
    };
}

这个宏将props作为一个映射传递给结构的给定构造函数。扩展,它看起来像这样:

#[derive(Debug)]
struct Apple {
    a: i32
}

trait Parent {
    type Child;
}

struct Mango;

impl Parent for Mango {
    type Child = Apple;
}

fn main() {
    let a = <Mango as Parent>::Child {
        a: 4
    };
    println!("{:?}", a);
}

编译它有错误:

error: expected one of `.`, `::`, `;`, `?`, or an operator, found `{`
  --> src/main.rs:25:38
   |
25 |     let a = <Mango as Parent>::Child {
   |                                      ^ expected one of `.`, `::`, `;`, `?`, or an operator here

我已经创建了一个宏来以类似的方式初始化一个结构,但是我无法用关联的类型来完成它。我认为编译器出于某种原因不支持它。即便如此,我想用这样的API创建一个宏。

我怎么能解决这个问题?

Link to Playground

2 个答案:

答案 0 :(得分:6)

像这样:

macro_rules! init {
    ($t:ty, { $( $k:ident =>  $v:expr ),* }) => {
        {
            type T = <$t as Parent>::Child;
            T {
                $( $k: $v ),*
            }
        }
    };
}

我的假设是这是解析器的限制,而不是编译器的类型分析。

答案 1 :(得分:-1)

我不认为可以初始化相关类型。

你可以做的可能是Child: K K是一个具有一些已知构造函数的特征(::new等...),然后调用该构造函数。

或者,您可以直接初始化T而不是Child