2016-10-21 3 views
2

특성에 체인 가능한 변환을 시도하고 있는데 문제가 있습니다.특성에 대한 체인 기능

나는 형태로의 변환 기능의 무리가 있습니다

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)) 
} 

하지만 컴파일 할 때 borrow checker는 타입 매개 변수 U 충분히 오래 살지 않습니다. 나는 나의 특성 경계가 내가 원하는 바라고 확신하고 평생 지시자를 가지고 여러 가지를 시도 했으므로 나는 걸림돌이되었다. (

추신 : 기능을 MyTrait에 일반화 할 수 있습니까? 생각하지 않는다

... 편집이 가능하지만, 우리는 결코 알지 못할 :

내가에서 말했듯에 의해 그의 대답에 @ 크리스 - 에머슨에 의해 제안 된 수정, 추가 한

의 의견, 내가 해결할 수없는 것 같은 다른 문제를 밝혀냈다.

Here은이 요령을 복잡하게하지 않기 위해 코드의 요지입니다. 요컨대

이 문제는 다음과 체인 함수 Box<T> 오브젝트 참조 해제해야하고 변환 함수에 T 통과하므로 TSized이어야한다. 그러나이 기능의 요점은 컴파일 타임에 임의의 (그리고 알려지지 않은) MyTrait 구현을 사용하는 것이 었습니다. 예를 들어 : 변환 함수는 & T 또는 & MUT T를 취할 수없는

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) 

그래서이 디자인이 작동하지 않을 수 있습니다 (이 할 수없는, 내가 출력을 생성하기 위해 입력을 소비해야하므로) .

+2

나는 'T'와 'U'가 다른 형질이라고 생각합니까? – LinearZoetrope

+0

@ Jsor : 아마도 'F'는 여기의 변압기이기 때문일 것입니다. –

+0

@MatthieuM. 나는 그들이 실제로 같은 형질의 두 가지 구현 사이에서 변환하고 그것을 boxed trait 객체로 변환하기를 원한다고 생각하고있다. – LinearZoetrope

답변

2

전체 컴파일러 메시지는 다음과 같습니다 컴파일러는 'static 평생 살 U이 필요하다고 말하고있다

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 

; 이것이 실제로 의미하는 것은 Box이 (컴파일러가 여기에서 아는 한) 영원히 살 수 있기 때문에 그 내부의 모든 참조가 유효해야한다는 것입니다.

그래서 수정은 간단하다 : 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)) 
} 

을 또한 동등한 것 U: 'static 바인딩 추가 추가.

+0

두 번째'U' 라인이 아닌'U : MyTrait + 'static'이라고 말하면 "빠르다. –

+0

그래, 그걸 고려해 봤어.하지만 경계를 경계로 추가하는 것이 더 낫다는 것이 임의로 결정되었다. 메모를 추가하겠습니다. –

+0

형식 매개 변수를 설명하는 두 번째 줄을 사용하는 것이 드문 것처럼 보입니다 (따라서 한눈에 보지 않을 수도 있음) – Neikos