On Fri, Aug 30, 2013 at 11:51:37PM +0200, bearophile wrote: > Joseph Rushton Wakeling: > > > static if (!__traits(hasMember, G, "directed") || > > !__traits(hasMember, G, "edge") || > > !__traits(hasMember, G, "edgeCount") || > > !__traits(hasMember, G, "vertexCount") || > > !__traits(hasMember, G, "isEdge") || > > !__traits(hasMember, G, "edgeID") || > > !__traits(hasMember, G, "addEdge") || > > !__traits(hasMember, G, "degreeIn") || > > !__traits(hasMember, G, "degreeOut") || > > !__traits(hasMember, G, "incidentEdgesIn") || > > !__traits(hasMember, G, "incidentEdgesOut") || > > !__traits(hasMember, G, "neighboursIn") || > > !__traits(hasMember, G, "neighboursOut")) > > Perhaps can shorten that code writing a hasMembers helper (and I > suggest to keep those names sorted): [...]
Here's a first stab at a possible implementation: /* Warning: untested code */ import std.typetuple : allSatisfy; template isString(T) { // There may already be something in Phobos that does // this, but I'm too lazy to look. enum isString = is(T == string); } template hasMembers(alias T, Members...) if (allSatisfy!isString(Members)) { // Template recursion + exprTuple slicing FTW :) enum hasMembers = __traits(hasMember, T, Members[0]) && hasMembers!(T, Members[1..$]); } void myFunc(G)(G graph) { static if (hasMembers!(G, "directed", "edge", /* ... */)) { ... } } T -- Computers shouldn't beep through the keyhole.