Ответ 1
Следующее работает, если вам нужно работать только со статическими функциями, а не с закрытием:
fn foo() {
println!("Foo");
}
fn bar() {
println!("Bar");
}
fn main() {
let selector = 0;
let test: fn() = match selector {
0 => foo,
_ => bar
};
test();
}
(попробуйте игровая площадка)
Здесь я использовал тип функции вместо функции.
Причина, по которой объект заимствованного объекта не работает, вероятно, следующий. Любой объект-объект представляет собой толстый указатель, который состоит из указателя на какое-то значение и указателя на виртуальную таблицу. Когда объект-признак создается из замыкания, все становится ясным - значение будет представлено самим замыканием (внутренне являющимся экземпляром структуры, содержащей все захваченные переменные), и виртуальная таблица будет содержать указатель на реализацию соответствующий признак Fn*()
, сгенерированный компилятором, чьим телом будет тело замыкания.
С функциями, однако, все не так ясно. Нет значения для создания объекта-объекта из-за того, что сама функция должна соответствовать реализации признака Fn()
. Следовательно, rustc, вероятно, генерирует пустую структуру и реализует для нее Fn()
, и эта реализация вызывает статическую функцию напрямую (не фактический Rust, а что-то близкое):
struct SomeGeneratedStructFoo;
impl Fn<()> for SomeGeneratedStructFoo {
type Output = ();
fn call(&self, args: ()) -> () {
foo();
}
}
Следовательно, когда объект-объект создается из fn foo()
, ссылка фактически делается на временное значение типа SomeGeneratedStructFoo
. Однако это значение создается внутри совпадения, и только ссылка на него возвращается из совпадения, поэтому это значение не проживает достаточно долго, и это то, о чем идет речь.