2016-10-21 4 views
2

私は形質上で連鎖可能な変換をしようとしていますが、いくつかの問題があります。形質上の機能の連鎖

私は、フォームの変換関数の束があります

fn transform<T: MyTrait>(in: T) -> impl MyTrait 

をそして私は私が私がこの機能

を書かれている

let mut val: Box<MyTrait> = ...; 
val = chain(val, transform1); 
val = chain(val, transform2); 
... 

を行うことができます機能chainをしたい

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:MyTraitに汎用のchain関数を作ることはできますか?私はその中で述べてきたようで、彼の答えに、@クリス・エマーソンが提案した修正を追加しました

:それが可能だとは思いませんが、私たちは...

EDITを知っていることはありませんかコメント、私は解決できないように見える別の問題を明らかにした。

Hereはこの記事を乱雑にしないためのコードの要点です。要するに

、問題がある:チェーン機能はBox<T>オブジェクト間接参照する必要があり、変換関数にTを渡すので、TSizedなければなりません。しかし、この機能の全体的なポイントは、任意の(そしてコンパイル時には未知の)実装を使用できるようにすることでした。たとえば、次のように

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(それができない、私は出力を生成するための入力を消費する必要があるとして)を取ることができない限り、このデザインが動作しないことができます。

+2

私は混乱しています、 'T'と' U'は異なる形質であるはずですか? – LinearZoetrope

+0

@ Jsor:おそらく、ここではFが変圧器であると仮定します。 –

+0

@MatthieuM。私は彼らが実際に同じ形質の2つの実装の間で変換し、それをボックス化された形質オブジェクトに変換したいと思っています。 – LinearZoetrope

答えて

2

フルコンパイラのメッセージは次のとおりです。

error[E0310]: the parameter type `U` may not live long enough 
--> <anon>:7:3 
    | 
7 | Box::new(f(*val)) 
    | ^^^^^^^^^^^^^^^^^ 
    | 
    = help: consider adding an explicit lifetime bound `U: 'static`... 
    note:...so that the type `U` will meet its required lifetime bounds 
--> <anon>:7:3 
    | 
7 | Box::new(f(*val)) 
    | ^^^^^^^^^^^^^^^^^ 

error: aborting due to previous error 

コンパイラはそれが'static寿命のために生きることUを必要としていることを言っています。これが実際に意味することは、Boxが(コンパイラがここで知っている限り)永遠に生き続けることができるため、その中の任意の参照が有効である必要があることです。

ので修正は簡単です:'staticUへ年代の境界を追加します。U: 'staticをバインド余分な追加

fn chain<T, U, F>(val: Box<T>, f: F) -> Box<MyTrait> 
    where T: MyTrait, 
     U: MyTrait + 'static, 
     F: FnOnce(T) -> U, 
{ 
    Box::new(f(*val)) 
} 

も相当します。

+0

2番目の 'U'行を挿入するのではなく、' U:MyTrait + 'staticと言うと "速く"なるかもしれません。 –

+0

ええ、私はそれを考慮しましたが、海水境界を追加することがより明確になると恣意的に決めました。私はメモを追加します。 –

+0

型パラメータを記述する2行目が珍しいように見えます(一見すると見えないかもしれません) – Neikos