www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to pass list of strings as compile-time parameters?

reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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[]

What gives?


T

-- 
Recently, our IT department hired a bug-fix engineer. He used to work for
Volkswagen.
Apr 24 2012
next sibling parent reply Trass3r <un known.com> writes:
 	bool compareByMemb(string[] ignores, T)(T obj1, T obj2) {
 		foreach (name; __traits(getAllMembers, T)) {
 			...
 		}
In this particular case you could try foo(T, U...)(T obj1, T obj2, U ignores)
Apr 24 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Apr 24, 2012 at 07:39:42PM +0200, Trass3r wrote:
	bool compareByMemb(string[] ignores, T)(T obj1, T obj2) {
		foreach (name; __traits(getAllMembers, T)) {
			...
		}
In this particular case you could try foo(T, U...)(T obj1, T obj2, U ignores)
Sure, but U always string. Though I suppose I *could* use a signature constraint to enforce that... T -- Guns don't kill people. Bullets do.
Apr 24 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Apr 24, 2012 at 10:47:53AM -0700, H. S. Teoh wrote:
 On Tue, Apr 24, 2012 at 07:39:42PM +0200, Trass3r wrote:
	bool compareByMemb(string[] ignores, T)(T obj1, T obj2) {
		foreach (name; __traits(getAllMembers, T)) {
			...
		}
In this particular case you could try foo(T, U...)(T obj1, T obj2, U ignores)
Sure, but U always string. Though I suppose I *could* use a signature constraint to enforce that...
[...] Well actually, U is a type tuple... but I want to constrain it to be always a tuple of strings. How would that work? T -- It is widely believed that reinventing the wheel is a waste of time; but I disagree: without wheel reinventers, we would be still be stuck with wooden horse-cart wheels.
Apr 24 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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[]

 What gives?


 T
Try using an alias parameter (with an optional type constraint). imo the template instantiation semantics needs a clean-up.
Apr 24 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Apr 24 2012