voile.munion
管理された共用体を提供する
- structTypeEnum(Types...) if (Types.length > 0 && (NoDuplicates!Types.length == Types.length));
- 型列挙Examples:alias U = TypeEnum!(int, string); U dat; // assign dat = 1; dat = U("foo"); dat.initialize!int(1); // cast assert(cast(int)dat == 1); // check assert(!dat.empty); assert(dat.check!int); assert(!dat.check!string); assert(dat.check!0); assert(!dat.check!1); // getter/setter assert(dat.tag == 0); assert(dat.get!int == 1); set!int(dat, 5); assert(dat.get!int == 5); // dat.set!1 = "foo"; // assert(dat.get!1 == "foo"); // clear dat.clear(); assert(dat.empty); // match dat = "foo"; assert(dat.match!( (int x) => x, (string str) => str.length) == "foo".length); - @trusted this(T)(auto ref T val)
 if(_inst.isAssignable!T);
- コンストラクタ
- voidopAssign(T)(auto ref T val)
 if(_inst.isAssignable!T);
- 代入
- inout(T)opCast(T)() inout
 if(_inst.isAssignable!T);
- キャスト
- boolopEquals()(TypeEnum rhs) const;
- 等号演算子オーバーロード
- size_ttoHash()() const;
- ハッシュ
 
- structTagged(U) if (is(U == union));
- タグ付き共用体Examples:union U { uint x; uint y; string str; } alias MU = Tagged!U; MU dat; dat.x = 10; assert(dat.tag == 0); assert(dat.x == 10); assert(dat.get!0 == 10); dat.str = "xxx"; assert(dat.get!2 == "xxx"); assert(dat.str == "xxx"); - boolopEquals()(Tagged rhs) const;
- 等号演算子オーバーロード
- size_ttoHash()() const;
- ハッシュ
- ref autoopDispatch(string member)()
 if(hasMember!(TaggedImpl!U.Instance, member));
 voidopDispatch(string member)(auto ref TaggedImpl!U.MemberType!member val)
 if(hasMember!(TaggedImpl!U.Instance, member));
- 名前アクセスTaggedの引数に共用体を与えた場合は名前でのアクセスを許可する。See Also:Managed
 
- Tagged!Utagged(U, size_t memberIndex, Args...)(auto ref Args args);
 Tagged!Utagged(U, string memberName, Args...)(auto ref Args args);
- Taggedの構築Examples:union U { uint x; uint y; } auto dat = tagged!(U, 0)(10); assert(dat.tag == 0); assert(dat.x == 10); dat = tagged!(U, "y")(20); assert(dat.tag == 1); assert(dat.y == 20); 
- structEndata(E) if (is(E == enum));
- データ付きのenumExamples:enum E { @data!int id, ignored, @data!string str, @data!int number, @data!string get, } mixin EnumMemberAlieses!E; alias EnumData = Endata!E; EnumData dat; // assign dat.initialize!str("test"); dat.number = 10; // check assert(!dat.empty); assert(dat.check!number); assert(!dat.check!str); // getter/setter assert(dat.tag == number); assert(.get!number(dat) == 10); dat.set!id = 5; assert(dat.tag == id); // clear dat.clear(); assert(dat.empty); // ignored member static assert(!__traits(compiles, dat.set!ignored(0))); - boolopEquals()(Endata rhs) const;
- 等号演算子オーバーロード
- size_ttoHash()() const;
- ハッシュ
- ref autoopDispatch(string member)()
 if(hasMember!(EndataImpl!E.Instance, member));
 voidopDispatch(string member)(auto ref EndataImpl!E.MemberType!member val)
 if(hasMember!(EndataImpl!E.Instance, member));
- 名前アクセス
 
- Endata!(typeof(tag))endata(alias tag, Args...)(auto ref Args payload);
- Endataの構築Examples:enum E { @data!int id, @data!int number, } mixin EnumMemberAlieses!E; auto dat = endata!id(10); assert(dat.tag == id); assert(dat.id == 10); 
- templateManagedUnion(Types...) if (Types.length > 0)
- 引数によって実装を切り替えるManagedUnion- 引数が1つでunionならTaggedになる
- 引数が1つでenumならEndataになる
- それ以外ならTypeEnumになる
 
- enum boolisTypeEnum(MU);
- TypeEnumか判定する
- enum boolisTagged(MU);
- Taggedか判定する
- enum boolisEndata(MU);
- Endataか判定する
- enum boolisManagedUnion(MU);
- ManagedUnionか判定する
- templateTagType(MU) if (isManagedUnion!MU)
- ManagedUnionのタグ型を得るExamples:static assert(is(TagType!(TypeEnum!(int, string)) == ubyte)); Examples:enum E { @data!int x, @data!string str } static assert(is(TagType!(Endata!E) == E)); 
- templateisAvailableTag(MU, alias tag) if (isManagedUnion!MU)
- 有効なタグか確認するExamples:alias MU = TypeEnum!(int, string); static assert( isAvailableTag!(MU, 1)); static assert(!isAvailableTag!(MU, 2)); Examples:enum E { @data!int x, @data!string str } static assert(isAvailableTag!(Endata!E, E.x)); static assert(isAvailableTag!(Endata!E, E.str)); static assert(!isAvailableTag!(Endata!E, getNotFoundTag!(Endata!E))); static assert(!isAvailableTag!(Endata!E, cast(E)3)); 
- templategetNotFoundTag(MU) if (isManagedUnion!MU)
- 無効なタグを取得するExamples:alias MU = TypeEnum!(int, string); static assert(getNotFoundTag!MU != 0); static assert(getNotFoundTag!MU != 1); Examples:enum E { @data!int x, @data!string str } alias MU = Endata!E; static assert(getNotFoundTag!MU != E.x); static assert(getNotFoundTag!MU != E.str); 
- templatehasType(MU, T) if (isTypeEnum!MU)
- 型を持っているか確認するExamples:alias MU = TypeEnum!(int, string); static assert(hasType!(MU, int)); static assert(hasType!(MU, string)); static assert(!hasType!(MU, long)); 
- templateEnumMemberTypes(MU) if (isManagedUnion!MU)
- 持っている型を列挙するExamples:alias MU = TypeEnum!(int, string); alias Types = EnumMemberTypes!MU; static assert(is(Types[0] == int)); static assert(is(Types[1] == string)); 
- templatememberTags(MU) if (isManagedUnion!MU)
 enum autoallTags(MU);
 templateEnumMemberTags(MU) if (isManagedUnion!MU)
- タグを列挙するExamples:alias MU = TypeEnum!(int, string); enum tags = memberTags!MU; static assert(tags.length == 2); static assert(tags[0] == 0); static assert(tags[1] == 1); alias MemberTags = EnumMemberTags!MU; static assert(MemberTags.length == 2); static assert(MemberTags[0] == 0); static assert(MemberTags[1] == 1); 
- templateTypeFromTag(MU, alias tag) if (isManagedUnion!MU)
- タグから型を得るExamples:alias MU1 = TypeEnum!(int, string); static assert(is(TypeFromTag!(MU1, 0) == int)); 
- templateisTypeAssignable(MU, T) if (isTypeEnum!MU)
- 型が代入可能か
- TagType!MUtag(MU)(auto ref const MU dat)
 if(isManagedUnion!MU);
- タグを確認するExamples:alias MU = TypeEnum!(int, string); MU tu; assert(tag(tu) == getNotFoundTag!MU); tu = 1; assert(tag(tu) != getNotFoundTag!MU); assert(tag(tu) == 0); tu = "1"; assert(tag(tu) != getNotFoundTag!MU); assert(tag(tu) == 1); Examples:enum E { @data!int x, @data!string str } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; assert(tag(dat) == getNotFoundTag!ED); dat.x = 1; assert(tag(dat) != getNotFoundTag!ED); assert(tag(dat) == x); dat.str = "1"; assert(tag(dat) != getNotFoundTag!ED); assert(tag(dat) == str); 
- voidinitialize(alias tag, MU, Args...)(auto ref MU dat, auto ref Args args)
 if(isManagedUnion!MU && isAvailableTag!(MU, tag));
 voidinitialize(T, MU, Args...)(auto ref MU dat, auto ref Args args)
 if(isTypeEnum!MU && hasType!(MU, T));
 voidinitialize(alias tag, MU)(auto ref MU dat)
 if(isEndata!MU && !isAvailableTag!(MU, tag) && (ImplOf!MU.getIndex!tag == cast(ImplOf!MU.IndexType)ImplOf!MU.notfoundTag));
- 初期化するExamples:struct S { int x; } alias MU = TypeEnum!(int, S); MU dat; initialize!0(dat, 1); assert(get!0(dat) == 1); initialize!1(dat, 100); assert(get!1(dat) == S(100)); // for type initialize!int(dat, 1000); assert(get!0(dat) == 1000); Examples:import std.datetime: Date; enum E { @data!int x, @data!Date date, test } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; initialize!x(dat, 1); assert(get!x(dat) == 1); initialize!date(dat, Date(2020, 8, 5)); assert(get!date(dat) == Date(2020, 8, 5)); initialize!test(dat); assert(tag(dat) == test); 
- @property voidset(alias tag, MU, T)(auto ref MU dat, auto ref T val)
 if(isManagedUnion!MU && isAvailableTag!(MU, tag));
 @property voidset(T, MU)(ref MU dat, auto ref T val)
 if(isTypeEnum!MU && hasType!(MU, T));
- データをセットするExamples:struct S { int x; } alias MU = TypeEnum!(int, S); MU dat; dat.set!0 = 1; assert(get!0(dat) == 1); set!1(dat, S(100)); assert(get!1(dat) == S(100)); // for type dat.set!int = 10; assert(dat.get!0 == 10); Examples:enum E { @data!int x, @data!string str } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; dat.set!x = 1; assert(dat.tag == x); set!str(dat, "test"); assert(dat.tag == str); 
- ref autoget(alias tag, MU)(auto ref inout MU dat)
 if(isManagedUnion!MU && isAvailableTag!(MU, tag));
 ref autoget(T, MU)(auto ref inout MU dat)
 if(isTypeEnum!MU && hasType!(MU, T));
- データを取得するExamples:import core.exception: AssertError; import std.exception; alias MU = TypeEnum!(int, string); MU tu; (() @trusted => assertThrown!AssertError(get!0(tu) == 1) )(); set!1(tu, "test"); assert(get!1(tu) == "test"); // for type assert(get!string(tu) == "test"); Examples:enum E { @data!int x, @data!string str } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; dat.set!x = 1; assert(.get!x(dat) == 1); dat.set!str = "test"; assert(dat.get!str == "test"); assert(dat.check!str); 
- boolcheck(alias tag, MU)(auto ref const MU dat)
 if(isManagedUnion!MU && isAvailableTag!(MU, tag));
 boolcheck(T, MU)(auto ref const MU dat)
 if(isTypeEnum!MU && hasType!(MU, T));
- データが入っていることを確認するExamples:alias MU = TypeEnum!(int, string); MU tu; assert(!tu.check!0); assert(!tu.check!1); tu.set!1 = "test"; assert(!tu.check!0); assert(tu.check!1); // for type assert(tu.check!string); Examples:enum E { @data!int x, @data!string str } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; dat.set!x = 1; assert(dat.check!x); dat.set!str = "test"; assert(dat.check!str); 
- voidclear(MU)(auto ref MU dat)
 if(isManagedUnion!MU);
- データをクリアするExamples:alias MU = TypeEnum!(int, string); MU tu; assert(!tu.check!0); assert(!tu.check!1); tu.set!1 = "test"; assert(!tu.check!0); assert(tu.check!1); tu.clear(); assert(!tu.check!0); assert(!tu.check!1); Examples:enum E { @data!int x, @data!string str } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; dat.set!x = 1; assert(check!x(dat)); dat.set!str = "test"; assert(check!str(dat)); 
- boolempty(MU)(auto ref const MU dat)
 if(isManagedUnion!MU);
- データがクリアされているか確認するExamples:alias MU = TypeEnum!(int, string); MU tu; assert(tu.empty); tu.set!1 = "test"; assert(!tu.empty); Examples:enum E { @data!int x, @data!string str } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; assert(dat.empty); dat.set!x = 1; assert(!dat.empty); dat.set!str = "test"; assert(dat.check!str); 
- aliasdata= AttrData(T);
- templatehasData(alias value)
- templategetDatas(alias value) if (hasData!value)
- unionData(alias e) if (hasData!e);
- templateEnumMemberAlieses(T) if (is(T == enum))
- templatematch(Funcs...)
- パターンマッチExamples:import std.exception; import std.conv: ConvException; import voile.misc: nogcEnforce; alias U = TypeEnum!(int, short, long); U dat; // マッチ関数を呼び出し dat.set!0 = 1; assert(dat.match!( (int x) => x + 1, /* call */ () => 50, (long x) => x + 100) == 2); // デフォルトを設定できる(empty || どれにもヒットしない) dat.clear(); assert(dat.match!( (int x) => x + 1, () => 50, /* call */ (long x) => x + 100) == 50); // 例外をキャッチできる dat = cast(long)5; assert(dat.match!( (Exception e) => 100, /* call 2 */ other => 50, (long x) => nogcEnforce(0)/* call 1 */) == 100); Examples:enum E { @data!int x, @data!string str } mixin EnumMemberAlieses!E; alias ED = Endata!E; ED dat; // マッチ関数を呼び出し 引数に Data!tag を指定することでマッチ対象指定 dat.x = 100; assert(dat.match!( (Data!x x) => x + 11 /* call */, () => 10) == 111); // マッチ関数を呼び出し 引数に @tag を指定することでマッチ対象指定 dat.str = "test"; assert(dat.match!( (@str x) => (cast(string)x).length + 11, other => 10) == 4 + 11);