optionally nullable type, null value is used if naryFun!visitors can't be called with provided arguments.
Fuses algebraic types on return.
1 static struct Asteroid { uint size; } 2 static struct Spaceship { uint size; } 3 alias SpaceObject = Variant!(Asteroid, Spaceship); 4 5 alias collideWith = autoMatch!( 6 (Asteroid x, Asteroid y) => "a/a", 7 // No visitor for A/S pair 8 // (Asteroid x, Spaceship y) => "a/s", 9 (Spaceship x, Asteroid y) => "s/a", 10 (Spaceship x, Spaceship y) => "s/s", 11 ); 12 13 import mir.utility: min; 14 // Direct access of a member in case of all algebraic types has this member 15 alias oops = (a, b) => (a.size + b.size) > 3 && min(a.size, b.size) > 1; 16 17 import mir.conv: to; 18 alias collide = (x, y) => oops(x, y) ? "big-boom".to!(typeof(collideWith(x, y))) : collideWith(x, y); 19 20 auto ea = Asteroid(1); 21 auto es = Spaceship(2); 22 auto oa = SpaceObject(ea); 23 auto os = SpaceObject(es); 24 25 // Asteroid-Asteroid 26 assert(collide(ea, ea) == "a/a"); 27 assert(collide(ea, oa) == "a/a"); 28 assert(collide(oa, ea) == "a/a"); 29 assert(collide(oa, oa) == "a/a"); 30 31 // Asteroid-Spaceship 32 // assert(collide(ea, es).isNull); // Compiler error: incompatible types 33 assert(collideWith(ea, es).isNull); // OK 34 assert(collide(ea, os).isNull); 35 assert(collide(oa, es).isNull); 36 assert(collide(oa, os).isNull); 37 38 // Spaceship-Asteroid 39 assert(collide(es, ea) == "s/a"); 40 assert(collide(es, oa) == "s/a"); 41 assert(collide(os, ea) == "s/a"); 42 assert(collide(os, oa) == "s/a"); 43 44 // Spaceship-Spaceship 45 assert(collide(es, es) == "big-boom"); 46 assert(collide(es, os) == "big-boom"); 47 assert(collide(os, es) == "big-boom"); 48 assert(collide(os, os) == "big-boom"); 49 50 // check types 51 52 static assert(!__traits(compiles, collide(Asteroid.init, Spaceship.init))); 53 static assert(is(typeof(collideWith(Asteroid.init, Spaceship.init)) == Nullable!())); 54 55 static assert(is(typeof(collide(Asteroid.init, Asteroid.init)) == string)); 56 static assert(is(typeof(collide(SpaceObject.init, Asteroid.init)) == string)); 57 static assert(is(typeof(collide(Spaceship.init, Asteroid.init)) == string)); 58 static assert(is(typeof(collide(Spaceship.init, SpaceObject.init)) == string)); 59 static assert(is(typeof(collide(Spaceship.init, Spaceship.init)) == string)); 60 61 static assert(is(typeof(collide(Asteroid.init, SpaceObject.init)) == Nullable!string)); 62 static assert(is(typeof(collide(SpaceObject.init, SpaceObject.init)) == Nullable!string)); 63 static assert(is(typeof(collide(SpaceObject.init, Spaceship.init)) == Nullable!string));
Behaves as match but doesn't enforce at compile time that all types can be handled by the visiting functions.