voile.munion
管理された共用体を提供する
- struct
TypeEnum
(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); - コンストラクタ
- void
opAssign
(T)(auto ref T val)
if(_inst.isAssignable!T); - 代入
- inout inout(T)
opCast
(T)()
if(_inst.isAssignable!T); - キャスト
- const bool
opEquals
()(TypeEnum rhs); - 等号演算子オーバーロード
- const size_t
toHash
()(); - ハッシュ
- struct
Tagged
(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");
- const bool
opEquals
()(Tagged rhs); - 等号演算子オーバーロード
- const size_t
toHash
()(); - ハッシュ
- ref auto
opDispatch
(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!U
tagged
(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);
- struct
Endata
(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)));
- const bool
opEquals
()(Endata rhs); - 等号演算子オーバーロード
- const size_t
toHash
()(); - ハッシュ
- ref auto
opDispatch
(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);
- template
ManagedUnion
(Types...) if (Types.length > 0) - 引数によって実装を切り替えるManagedUnion
- 引数が1つでunionならTaggedになる
- 引数が1つでenumならEndataになる
- それ以外ならTypeEnumになる
- enum bool
isTypeEnum
(MU); - TypeEnumか判定する
- enum bool
isTagged
(MU); - Taggedか判定する
- enum bool
isEndata
(MU); - Endataか判定する
- enum bool
isManagedUnion
(MU); - ManagedUnionか判定する
- template
TagType
(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));
- template
isAvailableTag
(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));
- template
getNotFoundTag
(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);
- template
hasType
(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));
- template
EnumMemberTypes
(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));
- template
memberTags
(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);
- template
TypeFromTag
(MU, alias tag) if (isManagedUnion!MU) - タグから型を得るExamples:
alias MU1 = TypeEnum!(int, string); static assert(is(TypeFromTag!(MU1, 0) == int));
- template
isTypeAssignable
(MU, T) if (isTypeEnum!MU) - 型が代入可能か
- TagType!MU
tag
(MU)(auto const ref 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);
- void
initialize
(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 void
set
(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 auto
get
(alias tag, MU)(auto inout ref MU dat)
if(isManagedUnion!MU && isAvailableTag!(MU, tag));
ref autoget
(T, MU)(auto inout ref 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);
- bool
check
(alias tag, MU)(auto const ref MU dat)
if(isManagedUnion!MU && isAvailableTag!(MU, tag));
boolcheck
(T, MU)(auto const ref 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);
- void
clear
(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));
- bool
empty
(MU)(auto const ref 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);
- alias
data
= AttrData(T); - template
hasData
(alias value) - template
getDatas
(alias value) if (hasData!value) - union
Data
(alias e) if (hasData!e); - template
EnumMemberAlieses
(T) if (is(T == enum)) - template
match
(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);