4.8 Sized
Sized 트레이트는 어떤 타입이 런타임에만 크기를 알 수 있는 DST(Dynamically sized types)이 아니라, 컴파일 시간에 크기를 알 수 있는, 이미 크기가 정해진(sized) 타입이라는 것을 알려준다.
어떤 행동도 구현할 필요 없는 Marker 트레이트이자, 타입 정의에 따라 자동으로 구현되는 Auto 트레이트다.
&str
은 참조로서 포인터를 가질 뿐 아니라 길이 필드도 갖고 있다. 하지만 포인터와 길이 필드는 usize
로 컴파일 시간에 크기를 알 수 있으므로, &str
은 Sized
다.
From
pub trait From<T>: Sized {
fn from(value: T) -> Self;
}
pub trait Into<T>: Sized {
fn into(self) -> T;
}
std::convert
모듈에는 위와 같은 트레이트가 정의되어 있는데, 슈퍼 트레이트(supertrait)와 묵시적 트레이트 바운드(implicit trait bounds)라는 개념이 들어 있다.
슈퍼 트레이트
From<T>: Size
d 는 From
이 Sized
의 서브 트레이트(subtrait)임을 암시한다(Sized는 From의 슈퍼 트레이트).
From
을 구현하는 타입이라면 반드시 Sized
도 구현해야 한다.
묵시적 트레이트 바운드
명시적으로 선언되지 않은 트레이트 바운드가 코드의 다른 부분에서 자동으로 추론되는 것을 의미한다.
컴파일러는 제네릭 타입 파라미터를 Sized
로 간주한다.
따라서 From
은 실제로는 아래와 같다. 제네릭 타입 T
역시 Sized
여야 한다.
pub trait From<T: Sized>: Sized {
fn from(value: T) -> Self;
}
부정 트레이트 바운드(Negative trait bound)를 사용하면 Sized 바운드를 해제할 수 있다.
pub struct Foo<T: ?Sized> {
// ^^^^^^^
// This is a negative trait bound
inner: T,
}
"T
는 Sized
일 수도 있고 아닐 수도 있다"를 의미한다. 그러므로 T를 DST에 바인딩할 수 있다.
From
과 Into
는 Dual 트레이트로, Into
는 From
을 구현하는 모든 타입에 대하여 blanket 구현을 사용해 구현된다.
blanket 구현(blanket implementation)은 모든 타입에 대한 트레이트 또는 특정 조건과 일치하는 모든 타입에 대한 트레이트를 구현한 것이다.
impl<T, U> Into<U> for T
where
U: From<T>,
{
fn into(self) -> U {
U::from(self)
}
}
타입 U
가 From<T>
를 구현한다면, T
에 대해 Into<U>
도 자동으로 구현된다.
그래서 실제로는 &str
에 대한 Into<String>
이 구현되어 있지 않지만, String
에 대한 From<&str>
은 구현되어 있으므로 let title = "A title".into()
와 같이 작성할 수 있다.
blanket 구현의 다른 예로는 Display
와 ToString
이 있다.
impl<T> ToString for T
where
T: Display + ?Sized,
{ ... }
ToString
을 구현하는 모든 타입은 Display
타입 역시 구현한다.
풀이
// TODO: WrappingU32에 대해 example이 컴파일되도록 From 트레이트를 구현하세요.
pub struct WrappingU32 {
value: u32,
}
impl From<u32> for WrappingU32 {
fn from(value: u32) -> WrappingU32 {
WrappingU32 { value }
}
}
fn example() {
let wrapping: WrappingU32 = 42.into();
let wrapping = WrappingU32::from(42);
}
u32
타입으로부터 WrappingU32
를 반환하는 From
트레이트를 구현한다.
From
트레이트는 from
함수를 갖고 있다. u32
타입을 받아 WrappingU32
타입으로 반환한다.
함수 본문은 WrappingU32
구조체에 u32
타입 매개변수 value
를 넣는다.