trait MyTrait { fn call(&self); } struct Foo; struct Bar; impl MyTrait for Foo { fn call(&self) { println!("Called from foo"); } } impl MyTrait for Bar { fn call(&self) { println!("Called from bar"); } } fn call_trait(a:&dyn MyTrait) { a.call(); } fn main() { let a = Foo; let b = Bar; call_trait( &a ); call_trait( &b ); }


trait 구현자를 호출할때 generic 을 씌우지 못할 상황에 있을 경우

위 처럼 dyn 으로 호출할 수 있는데 fat pointer 로 변환되어 넘어간다

fat pointer는 함수테이블, 데이터를 가리키므로 pointer x2 사이즈이며

또한 런타임시에 필요 함수를 복사하므로 오버헤드가 크다






enum MyEnum { A(Foo), B(Bar) } impl MyEnum { fn call(&self) { match self { Self::A( foo ) => foo.call(), Self::B( bar ) => bar.call() } } } struct Foo; struct Bar; impl Foo { fn call(&self) { println!("Called from foo"); } } impl Bar { fn call(&self) { println!("Called from bar"); } } fn call_enum(a:&MyEnum) { a.call(); } fn main() { let a = MyEnum::A( Foo ); call_enum( &a ); let b = MyEnum::B( Bar ); call_enum( &b ); }


enum dispatch 는 당연하게도 훨씬 빠르다. trait 복잡도에 dyn dispatch 보다 10배까지 빠르다

근데 문제는 위 의 예는 매우 단순하지만 enum 의 타입과 함수가 늘어나면 그만큼 똑같은 패턴의 코드를

반복 구현해야 한다.








extern crate enum_dispatch; #[enum_dispatch] enum MyEnum { A(Foo), B(Bar) } #[enum_dispatch(MyEnum)] trait MyEnumTrait { fn call(&self); } struct Foo; struct Bar; impl Foo { fn call(&self) { println!("Called from foo"); } } impl Bar { fn call(&self) { println!("Called from bar"); } } fn call_enum(a:&MyEnum) { a.call(); } fn main() { let a = MyEnum::A( Foo ); call_enum( &a ); let b = MyEnum::B( Bar ); call_enum( &b ); }


enum_dispatch 라는 proc-macro crate 를 사용하면 그 노동을 줄일 수 있다

당연하게도 enum 요소들의 함수 인터페이스는 동일해야 한다

이 crate 는 단순히 trait 에 맞춰 enum 에 단순 impl하는것이다