2014-12-03 5 views
4

나는 녹슨 열거 형을 사용하고 싶지만, 오류는 발생한다. 명백한 일생 동안의 녹 오류

error: explicit lifetime bound required 
numeric(Num), 
     ~~~ 

문제의 열거

는 :

enum expr{ 
    numeric(Num), 
    symbol(String), 
} 

내가 여기 빌린되고 이해 생각하지 않습니다. 나의 의도는 Num이나 String이 expr을 포함하는 것과 같은 수명을 가지고 함수에서 리턴 할 수있게하는 것이었다.

답변

8

오류 메시지가 다소 오도 된 것입니다. Num은 특성이며 동적 크기 형이므로 어떤 종류의 간접 참조 (참조 또는 Box)없이 값을 가질 수 없습니다. 그 이유는 간단합니다. 그냥 자문 해보십시오 : 어떤 크기 (바이트) expr 열거 형 값이 있어야합니까? 적어도 String만큼 크지 만, Num은 어떨까요? 임의의 유형은이 특성을 구현할 수 있으므로 소리가 나도록하려면 expr 크기가 무한대 여야합니다!

따라서 어떤 종류의 포인터 (예 : &Num 또는 Box<Num>)에서만 특성을 유형으로 사용할 수 있습니다. 포인터는 항상 고정 크기이며 특성 개체는 "뚱뚱한"포인터이므로 메서드 디스 패칭에 도움이되는 추가 정보가 유지됩니다.

또한 특성은 일반적으로 제네릭 형식 매개 변수의 경계로 사용됩니다. generics는 단일 형태이므로 컴파일 된 코드에서 정적 유형으로 변하기 때문에 크기가 항상 정적으로 알려지며 포인터가 필요하지 않습니다. 제네릭을 사용하는 것이 기본 접근 방식이어야하며 제네릭이 왜 작동하지 않는지 아는 경우에만 특성 개체로 전환해야합니다.

다음은 유형 정의의 가능한 변형입니다.

enum Expr<'a> { // ' 
    Numeric(&'a Num + 'a), 
    Symbol(String) 
} 

형질의 개체를 한 상자 :

enum Expr { 
    Numeric(Box<Num + 'static>), // ' // I used 'static because numbers usually don't contain references inside them 
    Symbol(String) 
} 

당신은 the official guide에 제네릭 및 특성에 대한 자세한 내용을보실 수 있습니다 비록에서 참조를 통해

enum Expr<N: Num> { 
    Numeric(N), 
    Symbol(String) 
} 

형질 개체 : 제네릭 형질 개체에 관한 정보가 부족한 순간. 당신이 뭔가를 이해하지 못하는지 물어보십시오.

enum Expr<'a> { // ' 
    Numeric(&'a Num + 'a), 
    Symbol(String) 
} 

에서 업데이트

'a 평생 매개 변수입니다. Numeric 변형 안에 참조 및 특성 개체 내부의 수명을 정의합니다. &'a Num + 'a은 적어도 'a 길이 인 "'a"과 같이 길이가 긴 참조 뒤에 특성 개체로 읽을 수있는 유형입니다. 즉, 먼저 'a을 참조 수명으로 지정합니다 (&'a). 둘째, 특성 개체 내부의 수명을 지정합니다 (Num + 'a). 후자는 특성이 내부의 참조를 포함하는 유형을 포함하여 모든 유형에 대해 구현 될 수 있기 때문에 필요합니다. 따라서 이러한 참조의 최소 수명을 특성 오브젝트 유형에도 넣어야합니다. 그렇지 않으면 특성 오브젝트에 대한 빌림 확인이 올바르게 작동하지 않습니다.

Box과 상황은 매우 유사합니다. Box<Num + 'static>은 "적어도 'static만큼 길다는 참조가있는 힙 할당 상자 내부의 특성 객체"입니다. Box 유형은 힙 할당 소유 데이터에 대한 스마트 포인터입니다. 보유한 데이터를 소유하기 때문에 참조와 같은 평생 매개 변수가 필요하지 않습니다. 그러나 특성 개체는 내부에 여전히 참조를 포함 할 수 있으므로 그 이유는 여전히 Num + 'a입니다. 방금 다른 평생 매개 변수를 추가하는 대신 'static 평생을 사용하기로했습니다. 숫자 형은 대개 간단하고 내부에 참조가 없기 때문에 'static bound와 같습니다. 물론 평생 매개 변수를 추가 할 수 있습니다. 이 거의 유용하지만 때문에,

&'a SomeTrait + 'b 

: 이러한 변형 모두가 올바른지

참고 :

&'a SomeTrait + 'a 
&'a SomeTrait + 'static 
Box<SomeTrait + 'a> // ' 
Box<SomeTrait + 'static> 

심지어이 다른 수명 매개 변수로 'a'b으로, 올바른 'b은 적어도 'a만큼 길어야합니다 (그렇지 않으면 특성 개체의 내부가 자체적으로 살아있을 때 무효화 될 수 있습니다). 너는 마찬가지로 &'a SomeTrait + 'a을 사용할 수있다.

+0

Symbol을 인스턴스화하면 컴파일러가 'N'에 대한 구체적인 유형을 유추하지 못하기 때문에 generic 버전을 사용하는 것이 어렵습니다. 더욱이,'Expr'이 하위 표현식을 포함하는 변형을 포함하도록 진화한다면, 일반 버전은 확장되지 않을 것입니다. 나는 일반적으로 일반적인 버전을 먼저 고려해야한다는 데 동의하지만,이 상황에서는 올바른 해결책이 아니라고 생각합니다. 또한, 요구 사항에 따라'Numeric (N)'을 복싱을 피하기 위해'Integer (i64)'와'Float (f64) '두 가지로 대체하는 것으로 충분할 수 있습니다. –

+0

감사합니다 이것은 정말로 도움이되었습니다. Numeric (& a a Num + 'a)와 Numeric (Box )의 정적 추가에 무엇을 추가할까요? . – ragingSloth

+0

@ragingSloth, 대답을 업데이트했습니다. –