Red Code, Green Code (nwcpp video)

Pragma ericanderton at yahoo.removeme.com
Tue May 8 10:40:49 PDT 2007


janderson wrote:
> sergk wrote:
>> I've just noticed a Northwest C++ Users Group presentation
>> "Red Code, Green Code:  Generalizing const" by Scott Meyers, and found 
>> it quite interesting.
>>
>> So here it is:
>> http://nwcpp.org/Meetings/2007/04.html
>>
>>
>> PS./OT: seems Scott do not really enjoying C++ template meta 
>> programming =)
>>
>> -- serg.
> 
> The next time some tries to argue library over language, or that 
> templates in C++ are perfect, we should point them to that video.
> 
> PS - What would be the nicest way to do this in D using current syntax?

Well, we can trans-literate from the C++ code to get the same results.  Here I have an example that replaces the 
functionality from the vector template with tuples, and some additional template namespaces and operations to make it 
all come together.  The actual example is in the bottom third of this snippet.

(Mucking with code from http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!207.entry)

// This is placed in the Public Domain

template Tuple(V...){
	alias V Tuple;
}

template InTuple(Item){
	const bool InTuple = false;
}

template InTuple(Item,First,V...){
	static if(is(Item == First)){
		const bool InTuple = true;
	}
	else alias InTuple!(Item,V) InTuple;
}

template TupleRemoveAll(Item){
	alias Tuple!() TupleRemoveAll;
}

template TupleRemoveAll(Item,First,V...){
	static if(is(Item == First)){
		alias TupleRemoveAll!(Item,V) TupleRemoveAll;
	}
	else alias Tuple!(First,TupleRemoveAll!(Item,V)) TupleRemoveAll;
}

// use template 'struct' to prevent tuple flattening when passing constraints around
template Constraints(V...){
	alias V list;
}

template ConstraintRemove(alias Constraints){
	alias Constraints.list list;
}

template ConstraintRemove(alias Constraints,First,V...){
	alias Cosntraints!(TupleRemoveAll!(First,Constraints.list)) newConstraints;
	alias Tuple!(newConstraints,ConstraintRemove!(newConstraints,V)) list;
}

struct IgnoreConstraints {}

template ConstraintCheck(alias Local,Caller:IgnoreConstraints){
	const bool ConstraintCheck = true;
}

// ensure that all local constraints are satisfied by caller
template ConstraintCheck(alias Local,alias Caller){
	static if(Local.list.length > 0){
		static if(Caller.list.length > 0){
			alias Local.list[0] first;
			static if(InTuple!(Local.list[0],Caller.list)){
				alias Constraints!(TupleRemoveAll!(first,Local.list)) newLocalConstraints;
				alias ConstraintCheck!(newLocalConstraints,Caller) ConstraintCheck;
			}
			else{
				const bool ConstraintCheck = false;
			}
		}
		else{ // nothing left to check
			const bool ConstraintCheck = false;
		}		
	}
	else{ // nothing left to check
		const bool ConstraintCheck = true;
	}
}

// Here's the useful part:
struct ExceptionSafe {}
struct LGPLed {}
struct Reviewed {}

void f(alias CallerConstraints)(Params params){
     alias Constraints!(ExceptionSafe) MyConstraints;
     static assert(ConstraintCheck!(MyConstraints,CallerConstraints));
     /* do something */
}

void g(alias CallerConstraints)(){
     alias Constraints!(ExceptionSafe,Reviewed) MyConstraints;
     static assert(ConstraintCheck!(MyConstraints,CallerConstraints));

     // try to call the other function
     f!(MyConstraints)();  // error, trying to call unreviewed code from reviewed code
     f!(ConstraintRemove!(MyConstraints,Reviewed))(); // ok, ignore Reviewed constraint
     f!(IgnoreConstraints)(); // ok, explicitly ignore constraints entirely
}

void main(){
     alias Constraints!(ExceptionSafe,Reviewed) MyConstraints;
     g!(MyConstraints)();
}

This won't compile under DMD 0.012 and later - Bug 1196 keeps operations like InTuple!() from operating correctly.  So 
this is only half-tested.  There are also a few different ways one could implement this.  I opted for this particular 
definition of Constraints!() to allow for the ConstraintCheck!() operation to work for comparing two tuple lists 
(otherwise, they'd collapse into a single tuple).

Aside from the advantages that tuples offer, I'm having a hard time seeing a clear advantage over the C++ version.  We 
still get template bloat, and namespace concerns, plus it's not much more readable.  At a minimum, the lack of a need 
for a heavy amount of compile-time code is a clear advantage and I think (not sure here) the concerns about virtual 
methods are also addressed thanks to D's design.  So I think this edges out the C++ version rather invisibly.

-- 
- EricAnderton at yahoo



More information about the Digitalmars-d mailing list