On Wednesday, 30 May 2018 at 14:40:50 UTC, Steven Schveighoffer
wrote:
On 5/30/18 4:27 AM, FeepingCreature wrote:
There's a very common idiom where in order to report line
numbers of an error or a log line at the callsite of a
function, you pass __FILE__ and __LINE__ as default parameters:
void foo(string file = __FILE__, size_t line = __LINE__);
What's wrong with this?
Say you add a string parameter, such as
void foo(string msg, string file = __FILE__, size_t line =
__LINE__);
foo("Hello World");
Now when you accidentally grab an old version of the library,
your new code will still run, but it will believe that it's
being called from file "Hello World", line 15. Not good.
Luckily there's a fix. Just stick this in some common header
file in your project:
struct CallerInfo
{
string file;
size_t line;
}
void foo(string msg, CallerInfo caller = CallerInfo(__FILE__,
__LINE__));
Now you cannot accidentally invoke foo with a string, or in
fact any type except another instance of CallerInfo.
Awesome idea! Unfortunately, it doesn't work. The __FILE__ and
__LINE__ there are not from the caller, but from the line that
defines foo.
See here: https://run.dlang.io/is/siz9YZ
https://run.dlang.io/is/oMe7KQ
Less elegant, but solves the problem of accidental argument
adding (CallerFile acts as a barrier). Unfortunately, while it
works in theory, in practice the compiler crashes.... LOL