函数指针的类型推导

问题描述 投票:0回答:1

这个答案解释了许多具有相同签名的函数具有不同的类型。
如果我们必须考虑具有公共类型的这些函数,即使对其中一个函数进行近似强制转换也足以使编译器认为所有函数都具有相同的类型。

在以下示例的第一个循环中,如果我们撤回

as fn(_, _) -> _
强制转换,编译器会抱怨本问题开头引用的答案中解释的原因。

但是,在第二个循环中,不需要强制转换来使编译器认为所有函数具有相同的类型;这与上面给出的原因不符...
问题:为什么函数指针的类型推导中元组的存在或不存在会发生变化?

在第三个循环中,我们可以通过一个技巧避免引入强制,并且仍然获得预期的元组,但这不是很方便(元组的各个成员彼此相距较远)。
附属问题:有没有一种方法可以方便地转换第一个循环而不需要强制?

fn add(
    l: i32,
    r: i32,
) -> i32 {
    l + r
}

fn multiply(
    l: i32,
    r: i32,
) -> i32 {
    l * r
}

fn main() {
    // https://stackoverflow.com/a/54629954/11527076
    for (name, operation) in [
        ("add", add as fn(_, _) -> _ /* coercion needed */),
        ("multiply", multiply),
    ] {
        println!("{} ~~> {}", name, operation(10, 2));
    }

    for operation in [add /* no coercion ??? */, multiply] {
        println!("~~> {}", operation(10, 2));
    }

    for (name, operation) in
        std::iter::zip(["add", "multiply"], [add, multiply])
    {
        println!("{} ~~> {}", name, operation(10, 2));
    }
}
/*
add ~~> 12
multiply ~~> 20
~~> 12
~~> 20
add ~~> 12
multiply ~~> 20
*/
rust
1个回答
0
投票

强制会尝试将数组中的元素统一为同一类型,但它所能做的只是相当于

array_elem as T
;它无法查看元组内部以强制元组成员进行统一工作。因此它可以尝试
("add", add) as _
,但元组不是原始类型,因此强制转换实际上无法完成任何事情。在第二个和第三个示例中,它所做的相当于
add as _
,这是一个原始转换,因此是允许的。

您可以在此处查看允许的类型强制:https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions

© www.soinside.com 2019 - 2024. All rights reserved.