Rustでイテレート可能なタプルを作ってみた。
これを使えば可変個引数とか出来るかもしれない。
//型宣言用 (型1, (型2, (型3, ()))) こんなタプルになる
#[macro_export]
macro_rules! variadic_type {
{ $t:ty } => { ($t,()) };
{ $t:ty,$($u:ty),+ } => { ($t, variadic_type!($($u),+)) };
}
//インスタンス用 (値1, (値2, (値3, ()))) こんなタプルになる
#[macro_export]
macro_rules! variadic {
{ $e:expr } => { ($e,()) };
{ $e:expr,$($f:expr),+ } => { ($e, variadic!($($f),+)) };
}
//◯番目の値を取得
//力技にせざるを得なかった
#[macro_export]
macro_rules! variadic_get {
{ $e:expr,0 } => { &$e.0 };
{ $e:expr,1 } => { &($e.1).0 };
{ $e:expr,2 } => { &(($e.1).1).0 };
{ $e:expr,3 } => { &((($e.1).1).1).0 };
{ $e:expr,4 } => { &(((($e.1).1).1).1).0 };
//たくさん増やしておこう
}
//variadic_getのmutable版
#[macro_export]
macro_rules! variadic_get_mut {
{ $e:expr,0 } => { &mut $e.0 };
{ $e:expr,1 } => { &mut ($e.1).0 };
{ $e:expr,2 } => { &mut (($e.1).1).0 };
{ $e:expr,3 } => { &mut ((($e.1).1).1).0 };
{ $e:expr,4 } => { &mut (((($e.1).1).1).1).0 };
}
//各要素に対して、順次同じメソッドを呼ぶためのimplを定義する
#[macro_export]
macro_rules! variadic_impl {
{ $p:path,$i:ident } => {
impl $p for (()) {
fn $i(&mut self) {
}
}
impl<T,U> $p for (T,U) where T:$p, U:$p {
fn $i(&mut self) {
(self.0).$i();
(self.1).$i();
}
}
}
}
使い方はこんな感じ
pub trait Update {
fn update(&mut self);
}
struct Test1 {
}
impl Update for Test1 {
fn update(&mut self) {
println!("test1");
}
}
struct Test2 {
}
impl Update for Test2 {
fn update(&mut self) {
println!("test2");
}
}
struct Test3 {
i: i32,
}
impl Update for Test3 {
fn update(&mut self) {
println!("test3 {}", self.i);
}
}
fn main() {
//型宣言したいならこう(使わなくてもOK)
type TTT = variadic_type!(Test1,Test2,Test3);
//インスタンスつくる
let mut v:TTT = variadic!(Test1{}, Test2{},Test3{i:1});
//Update::updateが呼べるように準備
variadic_impl!(Update,update);
//呼ぶ!
v.update();
{
//中身を変更してみる
let a = variadic_get_mut!(v, 2);
a.i = 10;
}
//呼ぶ!
v.update();
}
実行結果
test1
test2
test3 1
test1
test2
test3 10
こちらで試せます。
https://play.rust-lang.org/?gist=0e08f1648251d02a016d6d3d4e75185e&version=stable&mode=debug