www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template elegance?

reply "David Monagle" <david.monagle intrica.com.au> writes:
Hi guys,

I was hoping some of you more experience D guys could educate me 
on this one.

Given the following code:

///////

// Template function

bool shouldValue(alias operation, string description, E, V)(lazy 
E expression, V value, string name="Value", string file = 
__FILE__, typeof(__LINE__) line = __LINE__) {
	if (operation(expression, value)) return true;
	throw new FeatureTestException(format("%s should %s %s, but was 
actually %s", name, description, value, expression), file, line);
}

// Utility functions that use the above template

bool shouldEqual(E, V)(lazy E expression, V value, string 
name="Value", string file = __FILE__, typeof(__LINE__) line = 
__LINE__) {
	return shouldValue!((e, v) => e == v, "equal")(expression, 
value, name, file, line);
}
	
bool shouldBeGreaterThan(E, V)(lazy E expression, V value, string 
name="Value", string file = __FILE__, typeof(__LINE__) line = 
__LINE__) {
	return shouldValue!((e, v) => e > v, "equal")(expression, value, 
name, file, line);
}

///////

The above works just fine. If I call something like:

value.shouldBeGreaterThan(5)

I get the expected results.

What I was looking for is a more elegant way of defining those 
secondary functions. Originally I was hoping I could do something 
like:

enum shouldEqual(E, V) = shouldValue((e, v) => e == v, "equal", 
E, V);

But that doesn't work as any call to result.shouldEqual(5) does 
results in the template being called with no TEMPLATE parameters. 
I understand this, however I was hoping there was a nice way of 
defining this functionality. I concede that my code above may 
already be as short and concise as I can get it.

Thanks in advance!

David.
Jun 03 2015
parent reply "anonymous" <anonymous example.com> writes:
On Wednesday, 3 June 2015 at 09:10:22 UTC, David Monagle wrote:
 What I was looking for is a more elegant way of defining those 
 secondary functions. Originally I was hoping I could do 
 something like:

 enum shouldEqual(E, V) = shouldValue((e, v) => e == v, "equal", 
 E, V);
Here you go: ---- template shouldValue(alias operation, string description) { bool shouldValue(E, V)(lazy E expression, V value, string name="Value", string file = __FILE__, typeof(__LINE__) line = __LINE__) { if (operation(expression, value)) return true; throw new Exception(format("%s should %s %s, but was actually %s", name, description, value, expression), file, line); } } alias shouldEqual = shouldValue!((e, v) => e == v, "equal"); alias shouldBeGreaterThan = shouldValue!((e, v) => e > v, "be greater than"); ---- The trick is to split `shouldValue` into two nested templates. The outer template has those parameters that cannot be deduced: `operation` and `description`. The inner template has the parameters that should be deduced: `E` and `V`.
Jun 03 2015
parent "David Monagle" <david.monagle intrica.com.au> writes:
Wow, thanks very much anonymous. I did try that as a solution but 
stupid me was using an enum rather than an alias for the 
"shortcut" functions.

Been staring at the problem for so long that I couldn't see the 
problem right in front of me!

Appreciate the help greatly. Code now looks elegant again.
Jun 03 2015