import mir.conv: to; alias orElse(alias fun) = visit!(some!"a", none!fun); alias errToString = orElse!(to!string); // can any other type including integer enum @reflectErr static struct ErrorInfo { string msg; auto toString() const { return msg; } } alias V = Variant!(Err!string, ErrorInfo, Exception, long, double); alias R = typeof(errToString(V.init)); static assert(is(R == Variant!(string, long, double)), R.stringof); { V v = 1; assert(v.isOk); assert(errToString(v) == 1); } { V v = 1.0; assert(v.isOk); assert(errToString(v) == 1.0); } { V v = ErrorInfo("msg"); assert(!v.isOk); assert(errToString(v) == "msg"); } { V v = "msg".err; assert(!v.isOk); assert(errToString(v) == "msg"); } { V v = new Exception("msg"); enum line = __LINE__; assert(!v.isOk); assert(errToString(v) == "object.Exception@" ~ __FILE__ ~ "(" ~ line.stringof ~ "): msg"); }
suit, Err, isErr, isResultVariant, and reflectErr.
some is a variant of suit that forces that type of any argument doesn't satisfy isErr template.
none is a variant of suit that forces that type of all arguments satisfy isErr template. The handler automatically strips the Err wrapper.