string mixin only works once per block?

Dicebot public at dicebot.lv
Fri Apr 11 07:49:46 PDT 2014


On Friday, 11 April 2014 at 14:05:17 UTC, Vlad Levenfeld wrote:
> I'm trying to cut down on some boilerplate with this function:
>
> const string link (alias variable) ()
> {
> 	const string name = __traits (identifier, variable);
> 	return name~`= glGetUniformLocation (program, "`~name~`");`;
> }
>
> Applied in this kind of context:
> 		
> this ()
> {
> 	super ("default.vert", "gradient.frag");
> 	mixin link!start_color;
> 	mixin link!final_color;
> 	mixin link!center_pos;
> 	mixin link!lerp_vec;
> 	mixin link!lerp_range;
> }
> 					
>
> And the first mixin in every such function works fine, but the 
> rest don't. Specifically, I get this error:
>
> source/main.d(483): Error: mixin link!final_color link isn't a 
> template

This syntax is only supported by template mixins and you generate 
actual code as string. Template mixins can't be used inside 
functions and intended only for injecting declarations.

> for each mixin after the first. If I put the argument to mixin 
> in parenthesis:
>
> mixin (link!start_color);
>
> I get:
>
> source/main.d(483): Error: value of 'this' is not known at 
> compile time

This is unfortunate flaw of how class members get passed as an 
alias parameters. compiler tries to pass it together with context 
pointer (this) which can't happen because there is no valid 
context pointer at code generation point.

> Finally, removing the parenthesis and putting each mixin 
> statement in its own block:
>
> {mixin link!start_color;}
>
> compiles, but the mixed-in string has no apparent effect.

This does not mixin generated code but function itself, so it has 
no effect as expected.

To workaround context pointer limitation you can use tupleof + 
index trick:

const string link (T, size_t index) ()
	if (is(T == class) || is(T == struct))
{
	const string name = __traits (identifier, T.tupleof[index]);
	return name ~ `= 42;`;
}

class X
{	
	int a, b;
	
	this ()
	{
		mixin (link!(X, 0));
		mixin (link!(X, 1));
	}
}

void main()
{
	auto x = new X();
	import std.stdio;
	writeln(x.a, " ", x.b); // 42 42
}


More information about the Digitalmars-d-learn mailing list