Re: Capturing caller's file/line number in variadic template functions
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.
Re: Capturing caller's file/line number in variadic template functions
On Fri, 16 Mar 2012 14:41:40 -0400, H. S. Teoh wrote: On Fri, Mar 16, 2012 at 02:30:25PM -0400, Steven Schveighoffer wrote: [...] I know this is already answered, but do you get a stack trace? Shouldn't the second stack frame point to the offending line? [...] I didn't compile with debugging turned on, so it only showed a hex address. Using compile-time args for __FILE__ and __LINE__ lets me see the offending line even when debug is off. (And actually, the offending line is several frames down; the top few frames look like unittest scaffolding the compiler inserted for catching assert errors and handling unittest-specific stuff. Kinda painful to figure out where the problem is if a straight error message will tell you immediately. :-)) Right, but I dislike this sort of boilerplaty stuff, especially for unit tests. It should be avoidable... -Steve
Re: Capturing caller's file/line number in variadic template functions
16.03.2012 20:35, H. S. Teoh пишет: [...] 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 Yes, but the code is duplicated per every instance of template, and template is instantiated whenever it's CT-parameters change. This isn't much of a problem with functions that are meant to run at compile-time only (except that static locals will not work properly), but for run-time functions that may be undesired.
Re: Capturing caller's file/line number in variadic template functions
On Fri, Mar 16, 2012 at 02:30:25PM -0400, Steven Schveighoffer wrote: [...] > I know this is already answered, but do you get a stack trace? > Shouldn't the second stack frame point to the offending line? [...] I didn't compile with debugging turned on, so it only showed a hex address. Using compile-time args for __FILE__ and __LINE__ lets me see the offending line even when debug is off. (And actually, the offending line is several frames down; the top few frames look like unittest scaffolding the compiler inserted for catching assert errors and handling unittest-specific stuff. Kinda painful to figure out where the problem is if a straight error message will tell you immediately. :-)) T -- Indifference will certainly be the downfall of mankind, but who cares? -- Miquel van Smoorenburg
Re: Capturing caller's file/line number in variadic template functions
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);
Re: Capturing caller's file/line number in variadic template functions
On Fri, Mar 16, 2012 at 02:31:47PM -0400, Kevin Cox wrote: > On Mar 16, 2012 2:29 PM, "Adam D. Ruppe" 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.
Re: Capturing caller's file/line number in variadic template functions
On Fri, 16 Mar 2012 14:23:37 -0400, H. S. Teoh 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
Re: Capturing caller's file/line number in variadic template functions
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...
Re: Capturing caller's file/line number in variadic template functions
On Mar 16, 2012 2:29 PM, "Adam D. Ruppe" 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.
Re: Capturing caller's file/line number in variadic template functions
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) {
Re: Capturing caller's file/line number in variadic template functions
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. Is there an easy of working around this? T What happens if you insert some dummy type ?: void checkConsistency(T...)(T args, Delimiter dm = Delimiter.init, string file=__FILE__, size_t line=__LINE__) { ... }
Capturing caller's file/line number in variadic template functions
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