digitalmars.D.learn - How to pass list of strings as compile-time parameters?
- H. S. Teoh (16/16) Apr 24 2012 I'm trying to write a template function for doing member-wise
- Trass3r (2/6) Apr 24 2012 In this particular case you could try
- H. S. Teoh (6/14) Apr 24 2012 Sure, but U always string. Though I suppose I *could* use a signature
- H. S. Teoh (7/19) Apr 24 2012 [...]
- Timon Gehr (3/17) Apr 24 2012 Try using an alias parameter (with an optional type constraint). imo the...
- H. S. Teoh (52/71) Apr 24 2012 Thanks, that did it!
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
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
On Tue, Apr 24, 2012 at 07:39:42PM +0200, Trass3r wrote: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.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
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:[...] 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.Sure, but U always string. Though I suppose I *could* use a signature constraint to enforce that...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
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? TTry using an alias parameter (with an optional type constraint). imo the template instantiation semantics needs a clean-up.
Apr 24 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
Apr 24 2012