特性に連鎖可能な変換を行おうとしていますが、いくつか問題があります。
次の形式の変換関数がたくさんあります。
fn transform<T: MyTrait>(in: T) -> impl MyTrait
そして、chain
私ができるようにする機能が欲しい
let mut val: Box<MyTrait> = ...;
val = chain(val, transform1);
val = chain(val, transform2);
...
私はこの関数を書きました
fn chain<T, U, F>(val: Box<T>, f: F) -> Box<MyTrait>
where T: MyTrait,
U: MyTrait,
F: FnOnce(T) -> U {
Box::new(f(*val))
}
しかし、コンパイルすると、借用チェッカーは、型パラメーター U が十分に長く存続していないことを教えてくれます。私は自分の特性境界が私が望むものであると確信しており、ライフタイム指定子でさまざまなことを試したので、行き詰まっています:(
PS:chain
関数をジェネリックにすることは可能MyTrait
ですか? 私はそれが可能だとは思いませんが、私たちは決して知りません...
編集:
@chris-emerson が提案した修正を彼の回答に追加しました。コメントで述べたように、解決できないと思われる別の問題を発見しました。
この投稿を混乱させないように、コードの要点を次に示します。
要するに、問題は次のとおりです。チェーン関数はBox<T>
オブジェクトを逆参照T
し、を変換関数に渡すT
必要があるため、 Sized
. しかし、この関数の要点は、任意の (コンパイル時には不明な)MyTrait
実装を使用できるようにすることでした。例えば:
let mut val: Box<MyTrait> = ...;
//here we can know the type inside the Box
if ... {
val = chain(val, transform);
}
//but here we don't know anymore
//(its either the original type,
//or the type returned by transform)
したがって、変換関数が &T または &mut T を受け取ることができない限り、この設計は機能しません (出力を生成するために入力を消費する必要があるため、これはできません)。