Capturing caller's file/line number in variadic template functions

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Mar 16 11:35:37 PDT 2012


On Fri, Mar 16, 2012 at 08:26:30PM +0200, Mantis wrote:
> 16.03.2012 20:23, H. S. Teoh пишет:
> >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.
[...]
> What happens if you insert some dummy type ?:
> 
> void checkConsistency(T...)(T args, Delimiter dm = Delimiter.init,
>   string file=__FILE__, size_t line=__LINE__) { ... }


Actually, I found the solution: the compiler understands __FILE__ and
__LINE__ in compile-time arguments too, so this works:

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

It's a bit painful with the assert statement, because it doesn't let you
control the file/line number of the AssertError, but this can be worked
around by using std.string.format:

	assert(isConsistent(a),
		"inconsistency found in %s(%d)".format(file,line));

The AssertError will still point to checkConsistency, but the error
message will tell you where the caller is.


T

-- 
The early bird gets the worm. Moral: ewww...


More information about the Digitalmars-d-learn mailing list