2014-11-06 3 views
2

이 코드 :녹 : 매크로 형식 인수에 정적 함수를 호출하는 방법이 있습니까?

#![feature(macro_rules)] 

macro_rules! new(
    ($my_type:ty) => ($my_type::new()); 
) 

struct Foo { 
    blah: int 
} 

impl Foo { 
    fn new() -> Foo { 
     return Foo { blah: 0 } 
    } 
} 

fn main() { 
    let my_foo = new!(Foo); 
    println!("Foo's value: {}", my_foo.blah); 
} 

충분 보이는,하지만이 오류와 함께 실패합니다

test.rs:4:25: 4:32 error: unexpected token: `Foo` 
test.rs:4  ($my_type:ty) => ($my_type::new()); 
            ^~~~~~~ 

내가 매크로에 가서 컴파일과 잘 실행 Foo$my_type를 교체하는 경우, 그래서 Foo 그 위치에서 분명히 유효합니다. Foo이 매크로 대체에서 오는 것이 아니라면 분명히.

rustc test.rs --pretty expanded을 실행하면 확장 된 매크로가 표시되지 않습니다. 그것은 단지 나에게 같은 오류 메시지를 준다. 이것이 매크로를 확장하기 전에 메시지를 생성한다는 것을 의미하는 것으로 생각되지만, 컴파일이 성공하지 않으면 아무것도 표시하지 않을 수도 있습니다. 비록 이것이 유용성을 심각하게 제한 할지라도 --pretty expanded입니다.

다른 실험을 바탕으로, 매크로 유형 인수는 기본적으로 유형이 작동 할 것으로 예상되는 모든 다른 장소에서 사용할 수 있습니다. 정적 함수를 호출 할 수 없습니다. 다소 임의적 인 제한 사항처럼 보이며 오류 메시지는 분명 도움이되지 않습니다.

왜 이러한 제한이 존재합니까? 그리고 그 주위에 방법이 있습니까?

+1

'--pretty expanded'는 매크로 확장이 필요합니다. 따라서 확장이 실패 할 때 출력이 나오지 않습니다. –

+0

그게 당연한데 ... 당연히 ... 오류 메시지가 확장이 성공했다는 것을 의미하지만 확장 후에는 컴파일이 실패했다는 사실에서 혼란스러워졌습니다. 이것은 확장이 확장되지 않은 이름 인 $ my_type이 아닌 예상치 못한 실제 식별자 인 Foo를 참조한다는 사실에 기반합니다. –

답변

6

구문은 경로 Foo::bar을 생성하고 해당 함수를 호출하며 유효한 경로에서만 작동하며 임의의 유형 (예 : (u8, i8)::bar()이 작동하지 않습니다. 단일 식별자를 취하고 식별자 경로에 포함하는, 유효 whereever 사용될 수 ident 매크로 비 단말기를 사용할 수

#![feature(macro_rules)] 

macro_rules! new(
    ($my_type: ident) => ($my_type::new()); 
) 

struct Foo { 
    blah: int 
} 

impl Foo { 
    fn new() -> Foo { 
     return Foo { blah: 0 } 
    } 
} 

fn main() { 
    let my_foo = new!(Foo); 
    println!("Foo's value: {}", my_foo.blah); 
} 

구를 통해 임의의 유형에 대한 이러한 메소드를 호출 UFCS 쿠폰, <Type>::new() 및 그래서 구현되면 현재 매크로를

macro_rules! new(
    ($my_type: ty) => (<$my_type>::new()); 
) 

으로 대체해야합니다.

+0

사용 가능한 조각 지정자 목록은 [The Rust Macro Guide] (http://doc.rust-lang.org/guide-macros.html#invocation-syntax)를 확인했지만 "가장 일반적인" 그것은 분명히'ident'를 포함합니다); 확실한 목록을 얻을 수있는 곳을 알고 있습니까? –

+1

@MatthieuM. [출처] (https://github.com/rust-lang/rust/blob/e84e7a00ddec76570bbaa9afea385d544f616814/src/libsyntax/ext/tt/macro_parser.rs#L436-L464). – huon

+0

그게 효과가! 내 코드의 실제 매크로는 훨씬 더 복잡하고 실제로 경로가 아닌 여러 장소에서 유형을 사용합니다 ...하지만 놀랍게도 "ty"에서 "ident"로 전환하면 다른 어떤 것도 손상시키지 않았습니다. 사례. 즉, "타이 (ty)"를 사용한다고 생각할 수있는 유일한 이유는 명료성 때문입니다. 다른 이유가 있습니까? –

관련 문제