Static Foreach + Marking "compile time" variables

Chris Katko ckatko at gmail.com
Wed Mar 28 15:46:42 UTC 2018


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
		}
	}



More information about the Digitalmars-d-learn mailing list