www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Capturing caller's file/line number in variadic template functions

reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
I'm writing some unittests with very repetitive tests for a myriad of
different types, so I wrote a helper function:

	version(unittest) {
		void checkConsistency(T...)(T args) {
			foreach (a; args) {
				assert(isConsistent(a));
			}
		}
	}
	unittest {
		A a;
		B b;
		C c;
		checkConsistency(a,b,c);
	}

However, when a consistency check fails, the assert error points to
checkConsistency instead of the unittest, so it's a pain trying to
figure out exactly which test case failed. I tried adding default
arguments to checkConsistency:

	void checkConsistency(T...)(T args, string file=__FILE__,
		size_t line=__LINE__) { ... }

but this causes compile errors because when C==string, then the call is
ambiguous.

Is there an easy of working around this?


T

-- 
To err is human; to forgive is not our policy. -- Samuel Adler
Mar 16 2012
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 16 March 2012 at 18:21:54 UTC, H. S. Teoh wrote:
 	void checkConsistency(T...)(T args, string file=__FILE__,
 		size_t line=__LINE__) { ... }

 but this causes compile errors because when C==string, then the 
 call is
 ambiguous.

 Is there an easy of working around this?

Put the string file = blaha in the template argument list, before the variadic. voic checkConsistency(string file = __FILE__, int line = __LINE__, T...)(T t) {
Mar 16 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Mar 16, 2012 at 02:31:47PM -0400, Kevin Cox wrote:
 On Mar 16, 2012 2:29 PM, "Adam D. Ruppe" <destructionator gmail.com> wrote:
 Put the string file = blaha in the template argument list,
 before the variadic.

 voic checkConsistency(string file = __FILE__, int line = __LINE__,



No you don't. The compiler automatically infers the compile-time arguments for you. This works: int a; char b; float c; checkConsistency(a,b,c); // Gets translated to: checkConsistency!(__FILE__, __LINE__, int, char, float)(a,b,c); exactly as I wanted. T -- People say I'm arrogant, but they're just ignorant fools.
Mar 16 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 16 Mar 2012 14:23:37 -0400, H. S. Teoh <hsteoh quickfur.ath.cx>  
wrote:

 I'm writing some unittests with very repetitive tests for a myriad of
 different types, so I wrote a helper function:

 	version(unittest) {
 		void checkConsistency(T...)(T args) {
 			foreach (a; args) {
 				assert(isConsistent(a));
 			}
 		}
 	}
 	unittest {
 		A a;
 		B b;
 		C c;
 		checkConsistency(a,b,c);
 	}

 However, when a consistency check fails, the assert error points to
 checkConsistency instead of the unittest, so it's a pain trying to
 figure out exactly which test case failed.

I know this is already answered, but do you get a stack trace? Shouldn't the second stack frame point to the offending line? -Steve
Mar 16 2012
prev sibling next sibling parent Kevin Cox <kevincox.ca gmail.com> writes:
--0015174be302dc941204bb606b98
Content-Type: text/plain; charset=UTF-8

On Mar 16, 2012 2:29 PM, "Adam D. Ruppe" <destructionator gmail.com> wrote:
 Put the string file = blaha in the template argument list,
 before the variadic.

 voic checkConsistency(string file = __FILE__, int line = __LINE__,


--0015174be302dc941204bb606b98 Content-Type: text/html; charset=UTF-8 <p><br> On Mar 16, 2012 2:29 PM, &quot;Adam D. Ruppe&quot; &lt;<a href="mailto:destructionator gmail.com">destructionator gmail.com</a>&gt; wrote:<br> &gt;<br> &gt; Put the string file = blaha in the template argument list,<br> &gt; before the variadic.<br> &gt;<br> &gt; voic checkConsistency(string file = __FILE__, int line = __LINE__, T...)(T t) {<br> &gt;<br> &gt;<br> But then you have to write it each time.</p> --0015174be302dc941204bb606b98--
Mar 16 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 16 March 2012 at 18:31:58 UTC, Kevin Cox wrote:
 But then you have to write it each time.

Nah, it just works, at least for the implicit calls: checkConsistency(1, "2", 3); // calls checkConsistenct!(__FILE__, __LINE__, int, string, int)(1, "2", 3);
Mar 16 2012
prev sibling parent "Yuri Gorobets" <yuri.gorobets gmail.com> writes:
On Friday, 16 March 2012 at 18:21:54 UTC, H. S. Teoh wrote:
 	void checkConsistency(T...)(T args, string file=__FILE__,
 		size_t line=__LINE__) { ... }

 but this causes compile errors because when C==string, then the 
 call is
 ambiguous.

Does it make sense to consider to add a new type to hold the file name and line? So the types clash can be avoided: class file_line { this(string f=__FILE__, size_t ln=__LINE__) { file = f; line = ln; } string file; size_t line; }; void checkConsistency(T...) (T args, file_line pos = new file_line) {...} checkConsistency!(A,B,C)(a,b,c); Seems to work, but requires an explicit checkConsistency call - I didn't manage to make it implicit.
Mar 16 2012