Variables should have the ability to be @nogc

Marco Leise via Digitalmars-d digitalmars-d at puremagic.com
Tue May 31 12:04:39 PDT 2016


Am Tue, 31 May 2016 15:53:44 +0000
schrieb Basile B. <b2.temp at 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



More information about the Digitalmars-d mailing list