Static Foreach + Marking "compile time" variables

Chris Katko ckatko at gmail.com
Wed Mar 28 15:49:39 UTC 2018


On Wednesday, 28 March 2018 at 15:46:42 UTC, Chris Katko wrote:
> On Wednesday, 28 March 2018 at 08:05:55 UTC, Simen Kjærås wrote:
>> On Wednesday, 28 March 2018 at 07:45:59 UTC, Chris Katko wrote:
>>> I have a static foreach that goes through the parameter list 
>>> and if it sees a class like "rotate", ideally, I want it to 
>>> mark a boolean "has_rotate=true"
>>>
>>> Then simply later on, once I've parsed the list, I pick an 
>>> output path:
>>>
>>>     static if(has_rotate && has_position && has_scale)
>>>     {
>>>     //call C function al_draw_rotated_scaled_bitmap(...);
>>>     }
>>>
>>> So I pass a bunch of "options" and then based on those 
>>> options, it picks the right function to call instead of me 
>>> manually writing 
>>> draw_fixed_centered_rotated_scaled_colored_compressed_bitmap() manually.
>>>
>>> The problem is, I can foreach through those parameters all 
>>> just fine... but I can't "set" a marker.
>>>
>>> The error message makes perfect sense in retrospect:
>>>
>>>      variable has_position cannot be read at compile time
>>>
>>> has_position isn't a static/compile-time variable. The 
>>> question is... do they exist in D? Because otherwise, I'll be 
>>> going from a really clean, elegant solution that simply 
>>> passes through each parameter, and then reacts to the 
>>> combined result, and end up with something that has to "step 
>>> toward" the result, or perhaps, test every possible 
>>> permutation individually--so as to not need variables.
>>
>> D does not have compile-time variables. The way you'd 
>> generally do what you describe is with the templates in 
>> std.meta. Instead of something like this:
>>
>>     bool hasRotate= false;
>>     static foreach (e; MyTuple) {
>>         hasRotate |= is(e == Rotate);
>>     }
>>     static if (hasRotate) { // Fails, since b is a runtime 
>> variable.
>>         // Stuff
>>     }
>>
>> You'd be using a more functional style:
>>
>>     template isa(T) {
>>         enum isa(U) = is(U == T);
>>     }
>>
>>     enum hasRotate = anySatisfy!(isa!Rotate, MyTuple);
>>     static if (hasRotate) {
>>         // Stuff
>>     }
>>
>> --
>>   Simen
>
> Thank you for the reply! But I'm unable to get that code to 
> compile. For example:
>
> /usr/local/bin/../import/std/meta.d(883): Error: template 
> instance F!(_param_1) does not match template declaration 
> isIntegral(T)
> /usr/local/bin/../import/std/meta.d(888): Error: template 
> instance extra.funct2!(int, int, 
> int).funct2.anySatisfy!(isIntegral, _param_1) error 
> instantiating
> extra.d(264):        instantiated from here: 
> anySatisfy!(isIntegral, _param_1, _param_2, _param_3)
> extra.d(385):        instantiated from here: funct2!(int, int, 
> int)
> /usr/local/bin/../import/std/meta.d(883): Error: template 
> instance F!(_param_2) does not match template declaration 
> isIntegral(T)
> /usr/local/bin/../import/std/meta.d(888): Error: template 
> instance extra.funct2!(int, int, 
> int).funct2.anySatisfy!(isIntegral, _param_2) error 
> instantiating
> /usr/local/bin/../import/std/meta.d(889):        instantiated 
> from here: anySatisfy!(isIntegral, _param_2, _param_3)
> extra.d(264):        instantiated from here: 
> anySatisfy!(isIntegral, _param_1, _param_2, _param_3)
> extra.d(385):        instantiated from here: funct2!(int, int, 
> int)
> /usr/local/bin/../import/std/meta.d(883): Error: template 
> instance F!(_param_3) does not match template declaration 
> isIntegral(T)
> /usr/local/bin/../import/std/meta.d(889): Error: template 
> instance extra.funct2!(int, int, 
> int).funct2.anySatisfy!(isIntegral, _param_3) error 
> instantiating
> /usr/local/bin/../import/std/meta.d(889):        instantiated 
> from here: anySatisfy!(isIntegral, _param_2, _param_3)
> extra.d(264):        instantiated from here: 
> anySatisfy!(isIntegral, _param_1, _param_2, _param_3)
> extra.d(385):        instantiated from here: funct2!(int, int, 
> int)
>
>
> Perhaps I should post more of my code because there may be 
> subtle differences that are important:
>
> struct pos{float x, y;}
> struct scale{float f;}
> struct rotate{ float a; }
>
> void test_inst()
> 	{
> 	funct2(tile_bmp, pos(100,100), scale(2), rotate(0.0f));
>         //this worked with the foreach version
>         // in the case that it compiled and read the arguments
>         }
>
> Then I use your version:
>
> template isa(T) {
>         enum isa(U) = is(U == T); //is(typeof(U) == T)  doesn't 
> work either.
>      }
>
> void funct2(A...)(ALLEGRO_BITMAP *bitmap_bmp, A a)
> 	{
> 	enum hasRotate = anySatisfy!( isa(pos), a);  //if of type "pos"
>     static if (hasRotate)
> 		{
>                 // Stuff
> 		}
> 	}

Whoops! Wrong error message. That's if I replace isa(pos) with 
IsIntegral.

If I have isa(pos). It's almost identical:

/usr/local/bin/../import/std/meta.d(883): Error: template 
instance F!(_param_1) does not match template declaration isa(U)
/usr/local/bin/../import/std/meta.d(888): Error: template 
instance extra.funct2!(int, int, int).funct2.anySatisfy!(isa, 
_param_1) error instantiating
extra.d(263):        instantiated from here: anySatisfy!(isa, 
_param_1, _param_2, _param_3)
extra.d(385):        instantiated from here: funct2!(int, int, 
int)
/usr/local/bin/../import/std/meta.d(883): Error: template 
instance F!(_param_2) does not match template declaration isa(U)
/usr/local/bin/../import/std/meta.d(888): Error: template 
instance extra.funct2!(int, int, int).funct2.anySatisfy!(isa, 
_param_2) error instantiating
/usr/local/bin/../import/std/meta.d(889):        instantiated 
from here: anySatisfy!(isa, _param_2, _param_3)
extra.d(263):        instantiated from here: anySatisfy!(isa, 
_param_1, _param_2, _param_3)
extra.d(385):        instantiated from here: funct2!(int, int, 
int)
/usr/local/bin/../import/std/meta.d(883): Error: template 
instance F!(_param_3) does not match template declaration isa(U)
/usr/local/bin/../import/std/meta.d(889): Error: template 
instance extra.funct2!(int, int, int).funct2.anySatisfy!(isa, 
_param_3) error instantiating
/usr/local/bin/../import/std/meta.d(889):        instantiated 
from here: anySatisfy!(isa, _param_2, _param_3)
extra.d(263):        instantiated from here: anySatisfy!(isa, 
_param_1, _param_2, _param_3)
extra.d(385):        instantiated from here: funct2!(int, int, 
int)



More information about the Digitalmars-d-learn mailing list