問題一覧に戻る
上級マクロ
問題109: 属性マクロ
属性マクロは関数、構造体、モジュールに付与してコードを変換します。#[proc_macro_attribute]で定義し、属性引数と装飾対象の両方を受け取ります。関数の前後にログ出力を追加したり、自動的にベンチマークコードを生成するなど、アスペクト指向プログラミングが可能。tokioの#[main]やtestの#[test]が代表例。メタプログラミングの強力な手法で、ボイラープレートを削減し、横断的関心事を分離できます。
// 属性マクロ
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};
#[proc_macro_attribute]
pub fn (attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as );
let name = &input.sig.ident;
let output = quote! {
fn #name() {
println!("Function {} called", !(#name));
// 元の関数を埋め込む
#input
}
};
output.()
}
// 使用例
// main.rs:
use my_macro::trace;
#[trace]
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = ();
println!("Result: {}", result);
}