Thread overview
Capturing caller's file/line number in variadic template functions
Mar 16, 2012
H. S. Teoh
Mar 16, 2012
Adam D. Ruppe
Mar 16, 2012
Kevin Cox
Mar 16, 2012
Adam D. Ruppe
Mar 16, 2012
H. S. Teoh
Mar 17, 2012
Yuri Gorobets
March 16, 2012
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
March 16, 2012
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) {


March 16, 2012
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
March 16, 2012
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__,
T...)(T t) {
>
>
But then you have to write it each time.


March 16, 2012
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);
March 16, 2012
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__,
> T...)(T t) {
> >
> >
> But then you have to write it each time.

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.
March 17, 2012
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.