ちょwwwwwwwwwwwwwwwwwwwww
import std.typetuple; ////////////////////////////////////////////////////////////////////////////// /* * 配列 array のすべての要素を,順序を保ってタプルに展開する. */ template staticArrayToTuple(alias array) { static if (array.length) alias TypeTuple!(array[0], staticArrayToTuple!(array[1 .. $])) staticArrayToTuple; else alias TypeTuple!() staticArrayToTuple; } unittest { alias staticArrayToTuple!([ 1, 2, 3 ]) a; static assert(is(typeof(a) == TypeTuple!(int, int, int))); static assert(a[0] == 1); static assert(a[1] == 2); static assert(a[2] == 3); } ////////////////////////////////////////////////////////////////////////////// /* * モジュール mod から xids で指定された識別子以外の識別子を * import する選択的 import 文を生成する. */ template importExcept(string mod, xids...) { mixin (importExceptGen!(mod, xids).result); } // internal template importExceptGen(string mod, xids...) { // モジュールを仮に import して,識別子を読み込んでおく. mixin ("static import " ~ mod ~ ";"); /* * モジュール内のすべての識別子をタプルとして得る. * * このタプルにはコンパイラ内部だけで使われる識別子が * 含まれている.以下の処理ではまずそれを取り除き. * その後で,xid で指定された識別子を取り除く. */ mixin ("alias staticArrayToTuple!(" "__traits(allMembers, " ~ mod ~ ")) ids;"); /* * 渡された識別子文字列のタプルから,コンパイラ内部だけで * 使われる識別子を取り除き,result に結果のタプルをセットする. */ template sanitize(ids...) { template check1(string id) { /* .stringof を持たないならばコンパイラ内部の識別子なので, * import の対象から除外する.注意: コンパイラ内部の識別子 * でも .stringof を持つものがあるので,さらに check2 * を使って調べている.*/ static if (__traits(compiles, mixin(id ~ ".stringof"))) enum check1 = check2!(mixin(id ~ ".stringof")); else enum check1 = false; } template check2(string strof) { /* allMembers の戻り値には module, package が含まれる. * それらは .stringof を持ったコンパイラ内部の識別子なので, * import の対象から除外する.*/ enum check2 = (strof.length <= 7 || strof[0 .. 7] != "module ") && (strof.length <= 8 || strof[0 .. 8] != "package ") ; } static if (ids.length) { enum head = ids[0]; alias sanitize!(ids[1 .. $]).result tail; static if (check1!(mod ~ "." ~ head)) alias TypeTuple!(head, tail) result; else alias tail result; } else alias TypeTuple!() result; } /* * [CTFE] 所望の選択的 import 文を生成する. */ string generate(ids...)() { string stmt = "import " ~ mod ~ ": "; foreach (id; ids) { // xid で指定された識別子は除外する. foreach (xid; xids) { if (id != xid) { stmt ~= id ~ ", "; break; } } } return stmt[0 .. $ - 2] ~ ";"; } enum result = generate!(sanitize!(ids).result); } ////////////////////////////////////////////////////////////////////////////// // テスト mixin importExcept!("std.stdio", "writeln"); import std.stdio: p = writeln; static assert(__traits(compiles, writefln)); static assert(!__traits(compiles, writeln)); void main() { p("abc"); }
確かにこういうのは考えたけども.
import std.stdio : !writefln;
is expression, template mixin, stringof, __traitsあたりを使った黒魔術が炸裂.
D言語やべーな.