www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - mixins: declaration scope

reply mattcbro earthlink.net writes:
I am baffled about how to use mixins.  In the online documentation for mixin's
there is the following statement:

" Unlike a template instantiation, a template mixin's body is evaluated within
the scope where the mixin appears, not where the template declaration is
defined. It is analogous to cutting and pasting the body of the template into
the location of the mixin. It is useful for injecting parameterized
'boilerplate' code, as well as for creating templated nested functions, which is
not possible with template instantiations."

Unfortunately, the current version of the compiler does not evalute the mixin
where it is declared per se,  in that all declarations local to the location of
the mixin, but not visible to the template declaration cause compile errors.
For example consider the following code, which attempts to select one of two
possible computations:

template Foo(int select: 1) {
x = y + z - s.b ;
}
template Foo(int select: 0) {
x = y + z + s.b ;
}

struct stuff {
double b = 5 ;
}

int main(char[][] args)
{
stuff s ;
double x, y = 2.0, z = 3.0 ;
mixin Foo!(1) ;
printf("x = %g\n", x) ;
return(0) ;
}

This fails to compile with the error 
mixintest.d(2): no identifier for declarator x
mixintest.d(5): no identifier for declarator x

The first fix I could think of is to parameterize all undeclared variables in
the template declaration.  Unfortunately it would not let me pass in s.b as an
aliased argument to the mixin.  I finally got the following code to compile:

template Foo(alias y, alias z, alias q, int select: 1) 
{
double x = y + z - q ;
}
template Foo(alias y, alias z, alias q, int select: 0) 
{
double x = y + z + q ;
}

struct stuff {
double b = 5 ;
}

int main(char[][] args)
{
stuff s ;
double x, y = 2.0, z = 3.0, q = 5.0 ;
mixin Foo!(y, z, q ,1) ;
printf("x = %g\n", x) ;
return(0) ;
}

However, when I run it,  I get the following:
x = nan

I am trying to get the behavior of a conditional macro,  where I can make a
compile time decision about what code is actually inserted during the mixin
instantiation.  So far I have failed to duplicate the desired behaviour. I would
appreciate a clarification on how mixin's are interpreted.

-Matt
Apr 23 2005
parent "Ben Hinkle" <ben.hinkle gmail.com> writes:
<mattcbro earthlink.net> wrote in message 
news:d4epom$2n3l$1 digitaldaemon.com...
I am baffled about how to use mixins.  In the online documentation for 
mixin's
 there is the following statement:

 " Unlike a template instantiation, a template mixin's body is evaluated 
 within
 the scope where the mixin appears, not where the template declaration is
 defined. It is analogous to cutting and pasting the body of the template 
 into
 the location of the mixin. It is useful for injecting parameterized
 'boilerplate' code, as well as for creating templated nested functions, 
 which is
 not possible with template instantiations."

 Unfortunately, the current version of the compiler does not evalute the 
 mixin
 where it is declared per se,  in that all declarations local to the 
 location of
 the mixin, but not visible to the template declaration cause compile 
 errors.
 For example consider the following code, which attempts to select one of 
 two
 possible computations:

 template Foo(int select: 1) {
 x = y + z - s.b ;
 }
 template Foo(int select: 0) {
 x = y + z + s.b ;
 }

 struct stuff {
 double b = 5 ;
 }

 int main(char[][] args)
 {
 stuff s ;
 double x, y = 2.0, z = 3.0 ;
 mixin Foo!(1) ;
 printf("x = %g\n", x) ;
 return(0) ;
 }

 This fails to compile with the error
 mixintest.d(2): no identifier for declarator x
 mixintest.d(5): no identifier for declarator x
The template should have declarations instead of statements in the body.
 The first fix I could think of is to parameterize all undeclared variables 
 in
 the template declaration.  Unfortunately it would not let me pass in s.b 
 as an
 aliased argument to the mixin.  I finally got the following code to 
 compile:

 template Foo(alias y, alias z, alias q, int select: 1)
 {
 double x = y + z - q ;
 }
 template Foo(alias y, alias z, alias q, int select: 0)
 {
 double x = y + z + q ;
 }

 struct stuff {
 double b = 5 ;
 }

 int main(char[][] args)
 {
 stuff s ;
 double x, y = 2.0, z = 3.0, q = 5.0 ;
 mixin Foo!(y, z, q ,1) ;
 printf("x = %g\n", x) ;
 return(0) ;
 }

 However, when I run it,  I get the following:
 x = nan

 I am trying to get the behavior of a conditional macro,  where I can make 
 a
 compile time decision about what code is actually inserted during the 
 mixin
 instantiation.  So far I have failed to duplicate the desired behaviour. I 
 would
 appreciate a clarification on how mixin's are interpreted.
You could also pass the -inline flag to the compiler and use something like template Foo(int select: 1) { double Foo(double y,double z,double q) {return y + z - q ;} } template Foo(int select: 0) { double Foo(double y,double z,double q) {return y + z + q ;} } struct stuff { double b = 5 ; } int main(char[][] args) { stuff s ; double x, y = 2.0, z = 3.0, q = 5.0 ; x = Foo!(1)(y, z, q) ; printf("x = %g\n", x) ; return(0) ; } Typically C macros turn into inlined functions in D (see http://www.digitalmars.com/d/pretod.html#macros) so the above solution seems pretty natural. You could also use "version" statements to choose the different Foo implementations.
Apr 23 2005