개요
들어가기 앞서, 참고로 여기서 for
은 반복문 또는 트레잇 구현 키워드가 아닙니다.
여기서 사용된 키워드는 Higher Rank Trait Bounds
(HRTB
) 키워드입니다.
한국어로 직역하면 상위 트레잇 바운드인데, 일단 이는 잠시 저장해두고 아래의 예제를 보도록 합시다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
trait Foo<F> {
fn foo(&self, f: F) -> &usize;
}
struct Bar((usize, usize));
impl<T> Foo<T> for Bar
where
T: Fn(&(usize, usize)) -> &usize,
{
fn foo(&self, f: T) -> &usize {
f(&self.0)
}
}
fn main() {
let bar = Bar((5, 10));
let x = bar.foo(|s| &s.0);
println!("{x}");
}
제네릭 F
타입의 파라미터 f
를 갖는 foo
를 갖는 트레잇 Foo
와,
(usize, usize)
튜플 타입의 튜플을 받는 Bar
구조체가 구현되어있습니다.
아래에서 구현된 제네릭 F
는 Fn(&(usize, usize)) -> usize
로 트레잇 바운드를 해주었습니다.
foo
함수는 인자 f
를 실행하는 고차 함수입니다.
즉, main
함수에서 foo
를 호출하여 Bar
의 튜플에서 0
번째 인덱스의 값을 가져오는 코드입니다.
for 라이프타임
위 코드는 작동엔 문제 없으나, 어떠한 이유에서든 F
에 수명을 명시하고 싶을 때가 있습니다.
1
T: <'a> Fn(&'a (usize, usize)) -> &'a usize
하지만 이러한 코드는 작동하지 않습니다. 이럴 때 쓰이는 것이 for<'a>
입니다.
1
2
3
4
5
T: for<'a> Fn(&'a (usize, usize)) -> &'a usize
// 또는
for<'a> T: Fn(&'a (usize, usize)) -> &'a usize
놀랍게도 이게 끝입니다. 심지어 Fn
계열 트레잇 외엔 많이 쓰이지도 않습니다.