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