Jump to page: 1 2
Thread overview
Variable arguments with file and line information?
Nov 16, 2013
Namespace
Nov 16, 2013
Namespace
Nov 16, 2013
Jonathan M Davis
Nov 17, 2013
Dicebot
Nov 17, 2013
Jonathan M Davis
Nov 17, 2013
Dmitry Olshansky
Nov 17, 2013
Jonathan M Davis
Nov 17, 2013
Rob T
Nov 17, 2013
Jonathan M Davis
Nov 17, 2013
Rob T
Nov 17, 2013
Jonathan M Davis
Nov 17, 2013
Rob T
Nov 17, 2013
bearophile
Nov 17, 2013
Timothee Cour
November 16, 2013
Hi.
Is it possible to write something like that?
----
void error(Args...)(string msg, Args args, string file = __FILE__, size_t line = __LINE__) { ... }
----
?
Currently not, but how could it be done? I wont like to write:
----
error(format(msg, args));
----

Thanks in advance. :)
November 16, 2013
On Saturday, 16 November 2013 at 22:57:35 UTC, Namespace wrote:
> Hi.
> Is it possible to write something like that?
> ----
> void error(Args...)(string msg, Args args, string file = __FILE__, size_t line = __LINE__) { ... }
> ----
> ?
> Currently not, but how could it be done? I wont like to write:
> ----
> error(format(msg, args));
> ----
>
> Thanks in advance. :)

It is always surprising how quickly one has found its own solution, after you have posted here... :)

----
import std.stdio;
import std.string : format;

template error(string file = __FILE__, size_t line = __LINE__, Args...) {
	void error(string msg, Args args) {
		static if (args.length != 0)
			msg = .format(msg, args);
		
		writeln(.format(msg ~ ". In file %s on line %d.", file, line));
	}
}

void main()
{
	error("hallo");
	error("Hallo %s.", "du da");
}
----
November 16, 2013
On Sunday, November 17, 2013 00:09:53 Namespace wrote:
> On Saturday, 16 November 2013 at 22:57:35 UTC, Namespace wrote:
> > Hi.
> > Is it possible to write something like that?
> > ----
> > void error(Args...)(string msg, Args args, string file =
> > __FILE__, size_t line = __LINE__) { ... }
> > ----
> > ?
> > Currently not, but how could it be done? I wont like to write:
> > ----
> > error(format(msg, args));
> > ----
> > 
> > Thanks in advance. :)
> 
> It is always surprising how quickly one has found its own solution, after you have posted here... :)
> 
> ----
> import std.stdio;
> import std.string : format;
> 
> template error(string file = __FILE__, size_t line = __LINE__,
> Args...) {
> 	void error(string msg, Args args) {
> 		static if (args.length != 0)
> 			msg = .format(msg, args);
> 
> 		writeln(.format(msg ~ ". In file %s on line %d.", file, line));
> 	}
> }
> 
> void main()
> {
> 	error("hallo");
> 	error("Hallo %s.", "du da");
> }
> ----

If you're dealing with variadic arguments, then making the file and line number be template arguments is really your only solution. However, I must warn you that that will result in a new template instantation _every_ time that you use error, because the file and line number are always going to be different unless you call the function multiple times on the same line). So, this approach is pretty much guaranteed to generate template bloat. That may be acceptable, but I'd personally suggest trying to find a different way to go about solving the problem unless error is not going to be called very often - e.g. force the caller to call format when creating the message rather than supporting variadic arguments directly in error.

- Jonathan M Davis
November 17, 2013
Namespace:

> It is always surprising how quickly one has found its own solution, after you have posted here... :)

This is a well known psychological phenomenon: when you explain your problem to other people you lay down the problem very well, its constraints, its invariants, your needs, and this helps a lot the problem-solving parts of your mind find a solution :-)

This phenomenon is so strong, that some researchers assume to know a topic well enough only after they have taught one class about it :-)

That's why keeping a "laboratory notebook" for your programming activities, where you write down and explain what you do and what you have done, helps solve your problems. Unfortunately many computer science teachers don't explain their students why and how to keep such notebook.

Bye,
bearophile
November 17, 2013
unfortunately this problem keeps arising every so often and the only thing we have are workarounds

to name a few:
digitalmars.D - Typesafe variadics in any position
feature request: special optional argument (__FILE__, ...) AFTER variadic
template


On Sat, Nov 16, 2013 at 3:55 PM, Jonathan M Davis <jmdavisProg@gmx.com>wrote:

> On Sunday, November 17, 2013 00:09:53 Namespace wrote:
> > On Saturday, 16 November 2013 at 22:57:35 UTC, Namespace wrote:
> > > Hi.
> > > Is it possible to write something like that?
> > > ----
> > > void error(Args...)(string msg, Args args, string file =
> > > __FILE__, size_t line = __LINE__) { ... }
> > > ----
> > > ?
> > > Currently not, but how could it be done? I wont like to write:
> > > ----
> > > error(format(msg, args));
> > > ----
> > >
> > > Thanks in advance. :)
> >
> > It is always surprising how quickly one has found its own solution, after you have posted here... :)
> >
> > ----
> > import std.stdio;
> > import std.string : format;
> >
> > template error(string file = __FILE__, size_t line = __LINE__,
> > Args...) {
> >       void error(string msg, Args args) {
> >               static if (args.length != 0)
> >                       msg = .format(msg, args);
> >
> >               writeln(.format(msg ~ ". In file %s on line %d.", file,
> line));
> >       }
> > }
> >
> > void main()
> > {
> >       error("hallo");
> >       error("Hallo %s.", "du da");
> > }
> > ----
>
> If you're dealing with variadic arguments, then making the file and line
> number
> be template arguments is really your only solution. However, I must warn
> you
> that that will result in a new template instantation _every_ time that you
> use
> error, because the file and line number are always going to be different
> unless
> you call the function multiple times on the same line). So, this approach
> is
> pretty much guaranteed to generate template bloat. That may be acceptable,
> but
> I'd personally suggest trying to find a different way to go about solving
> the
> problem unless error is not going to be called very often - e.g. force the
> caller to call format when creating the message rather than supporting
> variadic arguments directly in error.
>
> - Jonathan M Davis
>


November 17, 2013
On Saturday, 16 November 2013 at 23:55:47 UTC, Jonathan M Davis wrote:
>
> If you're dealing with variadic arguments, then making the file and line number
> be template arguments is really your only solution. However, I must warn you
> that that will result in a new template instantation _every_ time that you use
> error, because the file and line number are always going to be different unless
> you call the function multiple times on the same line). So, this approach is
> pretty much guaranteed to generate template bloat. That may be acceptable, but
> I'd personally suggest trying to find a different way to go about solving the
> problem unless error is not going to be called very often - e.g. force the
> caller to call format when creating the message rather than supporting
> variadic arguments directly in error.
>
> - Jonathan M Davis

Something I'm wondering: if one were to split the implementation along these lines:


void error (string file = __FILE__, size_t line = __LINE__, Args...) (string msg, Args args) {
    errorImpl(file, line, msg, args);
}

void errorImpl (Args...) (string file, size_t line, string msg, Args args) {...}


What are the chances of the middle-man function being inlined, thus cutting down on template bloat in the final product?  I should hope it would be practically guaranteed.
November 17, 2013
> What are the chances of the middle-man function being inlined, thus cutting down on template bloat in the final product?  I should hope it would be practically guaranteed.

Even full inlining can't and won't do anything about template bloat within D semantics. This approach will, however, make size of bloated instances neglectible effective negating much of the problem in stripped binary.
November 17, 2013
On Sunday, November 17, 2013 13:06:11 Chris Nicholson-Sauls wrote:
> Something I'm wondering: if one were to split the implementation along these lines:
> 
> 
> void error (string file = __FILE__, size_t line = __LINE__,
> Args...) (string msg, Args args) {
>      errorImpl(file, line, msg, args);
> }
> 
> void errorImpl (Args...) (string file, size_t line, string msg,
> Args args) {...}
> 
> 
> What are the chances of the middle-man function being inlined, thus cutting down on template bloat in the final product?  I should hope it would be practically guaranteed.

Without using -inline, the odds are zero. With the -inline... maybe. To be honest, dmd's inliner is horrible. e.g. it completely fails to inline any of std.ascii right now even though almost everything in there is a one line function. As I understand it, the fact that error and errorImpl are templates make it much more likely that they'll be inlined, but you'd have to compile them with -inline and look at the generated assembly code to find out for sure. We really, really need to improve the inliner.

But regardless, inlining has no effect on "template bloat." The fact that the function was inline does not get rid of the fact that it was instantiated, and it's possible that it would be inlined in some circumstances and not in others, making it so that the function definition would have to stick around. Also, I don't think that dmd does a very good job of stripping out template instantiations that aren't needed anymore (e.g. the ones used in template constraints like isForwardRange or isSomeString), so it _definitely_ isn't going to be smart enough to remove an instantiated template that's been inlined and then not used somewhere where it wasn't inlined.

- Jonathan M Davis
November 17, 2013
17-Nov-2013 16:36, Jonathan M Davis пишет:
> On Sunday, November 17, 2013 13:06:11 Chris Nicholson-Sauls wrote:
>> Something I'm wondering: if one were to split the implementation
>> along these lines:
>>
>>
>> void error (string file = __FILE__, size_t line = __LINE__,
>> Args...) (string msg, Args args) {
>>       errorImpl(file, line, msg, args);
>> }
>>
>> void errorImpl (Args...) (string file, size_t line, string msg,
>> Args args) {...}
>>
>>
>> What are the chances of the middle-man function being inlined,
>> thus cutting down on template bloat in the final product?  I
>> should hope it would be practically guaranteed.
>
> Without using -inline, the odds are zero. With the -inline... maybe. To be
> honest, dmd's inliner is horrible. e.g. it completely fails to inline any of
> std.ascii right now even though almost everything in there is a one line
> function.

At least we should fix this embarrassing limitation that kills  inlining of std.ascii on ALL compilers.

https://d.puremagic.com/issues/show_bug.cgi?id=10985

And it's not only std.ascii pretty much all non-templated stuff.

> We really, really need to improve the inliner.

Amen.

-- 
Dmitry Olshansky
November 17, 2013
On Sunday, November 17, 2013 16:49:11 Dmitry Olshansky wrote:
> At least we should fix this embarrassing limitation that kills  inlining of std.ascii on ALL compilers.
> 
> https://d.puremagic.com/issues/show_bug.cgi?id=10985

> And it's not only std.ascii pretty much all non-templated stuff.

Yeah, std.ascii is just a concrete example that I'm aware of.

- Jonathan M Davis
« First   ‹ Prev
1 2