How to pass list of strings as compile-time parameters?

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Apr 24 11:23:19 PDT 2012


On Tue, Apr 24, 2012 at 08:03:07PM +0200, Timon Gehr wrote:
> On 04/24/2012 07:37 PM, H. S. Teoh wrote:
> >I'm trying to write a template function for doing member-wise
> >comparisons between two objects, with an optional list of members to
> >ignore. But I can't seem to figure out the syntax for passing a list of
> >strings (or an AA of strings) to the function?
> >
> >I tried this:
> >
> >	bool compareByMemb(string[] ignores, T)(T obj1, T obj2) {
> >		foreach (name; __traits(getAllMembers, T)) {
> >			...
> >		}
> >	}
> >
> >but the compiler complains:
> >
> >	Error: arithmetic/string type expected for value-parameter, not string[]
[...]
> Try using an alias parameter (with an optional type constraint). imo
> the template instantiation semantics needs a clean-up.

Thanks, that did it!

For posterity, here's the code (which I think is generally usable for
many more things than I'm using it for in my code):

	bool membCmp(T)(T t1, T t2) {
		return membCmpIgnoring!(cast(string[])[])(t1, t2);
	}

	bool membCmpIgnoring(alias ignores, T)(T t1, T t2)
		if (is(typeof(ignores)==string[]))
	{
		nextMemb: foreach (name; __traits(allMembers, T)) {
			foreach (i; ignores) {
				if (name == i)
					continue nextMemb;
			}
			static if (__traits(compiles, &__traits(getMember, t1,
								name)))
			{
				alias typeof(__traits(getMember, t1, name))
					type;
				static if (!is(type==function))
				{
					auto val1 = __traits(getMember, t1, name);
					auto val2 = __traits(getMember, t2, name);
					if (val1 != val2)
						return false;
				}
			}
		}
		return true;
	}

Given two structs or objects, X and Y, this lets you do an easy
implementation of opEquals():

	bool opEquals(Object obj) {
		auto o = cast(typeof(this))obj;
		return obj && membCmp(this, o);
	}

If you wish to ignore some fields, say x and y, in the comparison, then
just do this:

	bool opEquals(Object obj) {
		auto o = cast(typeof(this))obj;
		return obj && membCmpIgnoring!(["x", "y"])(this, o);
	}


Question: is it possible to sugar up the syntax even more, by allowing
an array of aliases? Or is that pushing the template syntax a bit too
far? I.e., can we make it possible to write:

	membCmpIgnoring!(x,y)(this, o)

without the string list syntax?


T

-- 
Prosperity breeds contempt, and poverty breeds consent. -- Suck.com


More information about the Digitalmars-d-learn mailing list