Am Tue, 31 May 2016 15:53:44 +0000 schrieb Basile B. <b2.t...@gmx.com>:
> This solution seems smarter than using the existing '@nogc' > attribute. Plus one also for the fact that nothing has to be done > in DMD. I just constrained myself to what can be done in user code from the start. :) > Did you encounter the issue with protected and private members ? > > For me when i've tested the template i've directly got some > warnings. DMD interprets my 'getMember' calls as a deprecated > abuse of bug 314 but in dmd 2.069 I would get true errors. Actually it is in a large half-ported code base from C++ and I haven't ever had a running executable, nor did I test it with recent dmd versions. My idea was to mostly have @nogc code, but allow it for a transition time or places where GC use does not have an impact. Here is the code, free to use for all purposes. enum GcScan { no, yes, automatic } enum noScan = GcScan.no; template gcScanOf(T) { import std.typetuple; static if (is(T == struct) || is(T == union)) { enum isGcScan(alias uda) = is(typeof(uda) == GcScan); GcScan findGcScan(List...)() { auto result = GcScan.automatic; foreach (attr; List) if (is(typeof(attr) == GcScan)) result = attr; return result; } enum gcScanOf() { auto result = GcScan.no; foreach (i; Iota!(T.tupleof.length)) { enum memberGcScan = findMatchingUda!(T.tupleof[i], isGcScan, true); static if (memberGcScan.length == 0) enum eval = gcScanOf!(typeof(T.tupleof[i])); else enum eval = evalGcScan!(memberGcScan, typeof(T.tupleof[i])); static if (eval) { result = eval; break; } } return result; } } else { static if (isStaticArray!T && is(T : E[N], E, size_t N)) enum gcScanOf = is(E == void) ? GcScan.yes : gcScanOf!E; else enum gcScanOf = hasIndirections!T ? GcScan.yes : GcScan.no; } } enum evalGcScan(GcScan gc, T) = (gc == GcScan.automatic) ? gcScanOf!T : gc; template findMatchingUda(alias symbol, alias func, bool optional = false, bool multiple = false) { import std.typetuple; enum symbolName = __traits(identifier, symbol); enum funcName = __traits(identifier, func); template Filter(List...) { static if (List.length == 0) alias Filter = TypeTuple!(); else static if (__traits(compiles, func!(List[0])) && func!(List[0])) alias Filter = TypeTuple!(List[0], Filter!(List[1 .. $])); else alias Filter = Filter!(List[1 .. $]); } alias filtered = Filter!(__traits(getAttributes, symbol)); static assert(filtered.length <= 1 || multiple, symbolName ~ " may only have one UDA matching " ~ funcName ~ "."); static assert(filtered.length >= 1 || optional, symbolName ~ " requires a UDA matching " ~ funcName ~ "."); static if (multiple || optional) alias findMatchingUda = filtered; else static if (filtered.length == 1) alias findMatchingUda = filtered[0]; } -- Marco