Thread overview
Passing variadic template parameters AND default call site __FILE__, __LINE__ template parameters.
May 27
realhet
May 27
monkyyy
May 27
realhet
May 27
monkyyy
May 28
realhet
May 28
realhet
May 28
realhet
May 28
monkyyy
May 27

Hello,

template T1(string FILE=__FILE__, size_t LINE=__LINE__, A...)
{
enum T1 = FILE ~ LINE.text ~ A.text;
}

pragma(msg, T1!(__FILE__,__LINE__, "hello", " world")); //works
pragma(msg, T1!(__FILE__,__LINE__,i"Hello $("World")")); //works
pragma(msg, T1!(i"Hello $("World")")); //error: does not match template declaration `T1(string FILE = __FILE__, ulong LINE = __LINE__, A...)`

After "A..." I can't put anything, so it seems it is impossible to combine the two superpowers: call site evaluation and variadic template parameters.

I can do similar functionality by function evaluation, but not with template instantiation.
Is there a way to do this functionality?

May 27

On Tuesday, 27 May 2025 at 10:20:40 UTC, realhet wrote:

>

Hello,

template T1(string FILE=__FILE__, size_t LINE=__LINE__, A...)
{
enum T1 = FILE ~ LINE.text ~ A.text;
}

pragma(msg, T1!(__FILE__,__LINE__, "hello", " world")); //works
pragma(msg, T1!(__FILE__,__LINE__,i"Hello $("World")")); //works
pragma(msg, T1!(i"Hello $("World")")); //error: does not match template declaration `T1(string FILE = __FILE__, ulong LINE = __LINE__, A...)`

After "A..." I can't put anything, so it seems it is impossible to combine the two superpowers: call site evaluation and variadic template parameters.

I can do similar functionality by function evaluation, but not with template instantiation.
Is there a way to do this functionality?

import std;
template T2(string FILE=__FILE__, size_t LINE=__LINE__){
template T2(A...){
	alias T2=T1!(FILE,LINE,A);
}}
template T1(string FILE=__FILE__, size_t LINE=__LINE__,A...){
	enum T1 = FILE ~ LINE.text ~ A.text;
}
alias t2=T2!();
pragma(msg, t2!(i"Hello $("World")"));


/*
import std;
void main(){
	foreach(i;0..8){
		"alias a".write;
		i.write;
		"=void,".write;
}}
*/
template T3(alias a0=void,alias a1=void,alias a2=void,alias a3=void,alias a4=void,alias a5=void,alias a6=void,alias a7=void,string FILE=__FILE__, size_t LINE=__LINE__){
	alias A=AliasSeq!();
	static foreach(int I;0..8){
		alias B(int J:I)=mixin("a"~I.stringof);
		static if( ! is(B!I==void)){
			A=AliasSeq!(A,B!I);
	}}
	alias T3=T1!(FILE,LINE,A);
}

pragma(msg, T3!(i"goodbye $("World")"));


template pack(A...){
	alias unpack=A;
}
alias T4(alias A,string FILE=__FILE__, size_t LINE=__LINE__)=T1!(FILE,LINE,A.unpack);
pragma(msg, T4!(pack!(i"farwell $("World")")));
May 27

On Tuesday, 27 May 2025 at 15:01:38 UTC, monkyyy wrote:

>

On Tuesday, 27 May 2025 at 10:20:40 UTC, realhet wrote:

Hi and thanks for trying!

t2!(x) //The problem with this is the LINE will point to the alias declaration, not the pragma.

Interesting trick: template nested inside a template.

T3!(x) //This works perfectly, but the 8 alias has a really low limit on the contents of the IES string: 3 $() blocks and it's out of parameters. Maybe if I generate this template with a string mixin, but I'm affraid the compiler would go crazy. I'm planning to use it with 1000 lines of shader code and lots of constanst injected into that with $().

Interesting tricks: alias reassignment and templateParameterValueSpecialization (wow! It avoids the redeclaration error I normally get.).

T4!(pack!(x)) //Unlike T3, it has no limitations but it needs an extra work at the call site. The simplest extra work is manually writing FILE,LINE btw.

Interesting trick: How to pack a whole AliasSeq into a single slot. I got to rememper this, it's so cool. template pack(A...) { alias unpack=A; }

Final thoughts: I think the only conflict is on the language level, as the data form FILE and LINE are always accessible inside the compiler. But maybe in the future there will be a __traits for this. And also for COLUMN. But I also understand that these simple looking things are super complicated inside the compiler.

Thx for the template tricks!

May 27

On Tuesday, 27 May 2025 at 21:07:51 UTC, realhet wrote:

>

Interesting tricks: alias reassignment and templateParameterValueSpecialization (wow! It avoids the redeclaration error I normally get.).

There bugs here, it works in this case(I have theories why) and in opend its considered a regression and adr will undo "optimizations"; but this is unstable and considered unimportant by the core devs

Specialization as a lookup table is valid. Trying to escape references to static forloop, risky.

May 28

On Tuesday, 27 May 2025 at 21:16:57 UTC, monkyyy wrote:

>

On Tuesday, 27 May 2025 at 21:07:51 UTC, realhet wrote:

I stay in safety and choose this way:

enum _LOCATION_(string FILE=__FILE__, size_t LINE=__LINE__) = FILE~'('~LINE.text~",1)";

enum loc1 = (_LOCATION_!());
enum loc2 = (_LOCATION_!());

We just can't eliminate the !() with alias, it's mandatory.

And I write this signature (_LOCATION_!()) to every place where it is needed. But not by myself, by my machine. It will be hidden in my editor to reduce visual noise.

Maybe I can make it more type-safe by not returning a string "file.d(12,1)", but returning a struct. Howerer IES also starts and ends with special structs, easy to detect those.

May 28

On Wednesday, 28 May 2025 at 10:13:43 UTC, realhet wrote:

>

On Tuesday, 27 May 2025 at 21:16:57 UTC, monkyyy wrote:

>

On Tuesday, 27 May 2025 at 21:07:51 UTC, realhet wrote:

I've found a way to eliminate !() by using a function:

struct LOCATION_t2
{
    string location;
    string toString() const => location;
}

auto LOC2(string FILE=__FILE__, size_t LINE=__LINE__)
=> LOCATION_t2(FILE~'('~LINE.text~",1)");

pragma(msg, LOC2);				//LOCATION_t2("onlineapp.d(28,1)")
pragma(msg, LOC2.text);			//onlineapp.d(29,1)
pragma(msg, i"$(LOC2)");		//AliasSeq!(InterpolationHeader(), InterpolatedExpression(), LOC2, InterpolationFooter()) //!no line number
pragma(msg, i"$(LOC2)".text);	//onlineapp.d-mixin-31(31,1)  //!!line number is still there!

Also encapsulating it in a struct, so it's safer because (LOCATION_t2 != string).

I love this LEGO set :]

May 28
On Wednesday, May 28, 2025 5:04:06 AM Mountain Daylight Time realhet via Digitalmars-d-learn wrote:
> I've found a way to eliminate !() by using a function:

Just FYI, you almost never want to instantiate a template with a file and line number anyway, because that means that every single template instantiation is going to be unique, and that's going to mean a lot of template bloat.

Once in a blue moon, you do need the file or line number to be a template argument, but it's pretty much always better to make them function arguments if you can.

- Jonathan M Davis




May 28
On Wednesday, 28 May 2025 at 11:32:53 UTC, Jonathan M Davis wrote:
> On Wednesday, May 28, 2025 5:04:06 AM Mountain Daylight Time realhet via Digitalmars-d-learn wrote:
Yes, most of the time I can put __FILE__ and __LINE__ onto a runtime function parameter.

But this time it is a requirement:
I must write the __FILE__ and __LINE__ with pragma(msg, ...)

Update: I can only avoid !() when I'm in the same module.  When importing that function, into another module, there will be an implicit alias and it will lock onto a single __FILE__  __LINE__ location inside the imported module.



May 28
On Wednesday, 28 May 2025 at 11:32:53 UTC, Jonathan M Davis wrote:
> On Wednesday, May 28, 2025 5:04:06 AM Mountain Daylight Time realhet via Digitalmars-d-learn wrote:
>> I've found a way to eliminate !() by using a function:
>
> Just FYI, you almost never want to instantiate a template with a file and line number anyway, because that means that every single template instantiation is going to be unique, and that's going to mean a lot of template bloat.

Dememoization is necessary for lots of things.