www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - expression templates

reply "Mr enuhtac" <enuhtac_lists gmx.de> writes:
Hello everyone,

I'm new to D and this list (although I've had a look onto D a few years ago). I
hope you guys can help me with my questions.

At the moment I'm trying to implement some expression template stuff. My first
goal is to encode an expression into a type representing that expression
without any additional functionality (like the possibility to evaluate that
expression). Actually this is very simple and short in D. This is my approach:

struct OpBinary( string Op, R1, R2 )
{
    alias typeof( mixin( "R1.EvalT.init" ~ Op ~ "R2.EvalT.init" ) ) EvalT;

    enum string Operator = Op;
};

struct Constant( T, T v )
{
    alias T EvalT;

    enum T value = v;
};

struct Expr( R )
{
    auto opBinary( string Op, R2 )( Expr!R2 )
    {
        return Expr!( OpBinary!( Op, R, R2 ) )();
    }

    auto opBinary( string Op, T )( T v ) if( isNumeric!T )
    {
        return Expr!( OpBinary!( Op, R, Constant!( T, v ) ) )();
    }

    auto opBinaryRight( string Op, T )( T v ) if( isNumeric!T )
    {
        return Expr!( OpBinary!( Op, Constant!( T, v ), R ) )();
    }
};

But I cannot figure out how to implement expression templates for comparison
operators, which is crucial for my purpose. The opCmp function is great for
implementing comparison functionality, but when building an expression template
tree the information on the actual comparison operator is needed. opCmp just
knows that a comparison is going on, the actual type of comparison is unknown.
What I would like to have is something like this:

    auto opCmp( string Op, R2 )( Expr!R2 )
    {
        return Expr!( OpBinary!( Op, R, R2 ) )();
    }

So opCmp knows about the actual operator and would just use my OpBinary struct
to encode it. But this is not possible.

The only workaround for I this problem I can imagine is using my own comparison
functions instead of the comparison operators:
op!"<"( a, b ) instead of a < b.
Another possibility would be to call opBinary explicitly:
a.opCmp!"<"( b )
In this case I would not even have to write additional code.

But these workarounds are ugly, if would greatly prefer the normal comparison
operators.
Does anyone has an idea how to use them?

Regards,
enuhtac
-- 
GMX DSL Doppel-Flat ab 19,99 Euro/mtl.! Jetzt mit 
gratis Handy-Flat! http://portal.gmx.net/de/go/dsl
Mar 26 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Mr enuhtac:

 But these workarounds are ugly, if would greatly prefer the normal comparison
operators.
 Does anyone has an idea how to use them?

I don't know the answer. If no one will give you a good answer then I suggest you to ask the same question (with the same code example) in the main D newsgroup again. Bye, bearophile
Mar 26 2011
prev sibling parent Don <nospam nospam.com> writes:
Mr enuhtac wrote:
 Hello everyone,
 
 I'm new to D and this list (although I've had a look onto D a few years ago).
I hope you guys can help me with my questions.
 
 At the moment I'm trying to implement some expression template stuff. My first
goal is to encode an expression into a type representing that expression
without any additional functionality (like the possibility to evaluate that
expression). Actually this is very simple and short in D. This is my approach:
 
 struct OpBinary( string Op, R1, R2 )
 {
     alias typeof( mixin( "R1.EvalT.init" ~ Op ~ "R2.EvalT.init" ) ) EvalT;
 
     enum string Operator = Op;
 };
 
 struct Constant( T, T v )
 {
     alias T EvalT;
 
     enum T value = v;
 };
 
 struct Expr( R )
 {
     auto opBinary( string Op, R2 )( Expr!R2 )
     {
         return Expr!( OpBinary!( Op, R, R2 ) )();
     }
 
     auto opBinary( string Op, T )( T v ) if( isNumeric!T )
     {
         return Expr!( OpBinary!( Op, R, Constant!( T, v ) ) )();
     }
 
     auto opBinaryRight( string Op, T )( T v ) if( isNumeric!T )
     {
         return Expr!( OpBinary!( Op, Constant!( T, v ), R ) )();
     }
 };
 
 But I cannot figure out how to implement expression templates for comparison
operators, which is crucial for my purpose. The opCmp function is great for
implementing comparison functionality, but when building an expression template
tree the information on the actual comparison operator is needed. opCmp just
knows that a comparison is going on, the actual type of comparison is unknown.
 What I would like to have is something like this:
 
     auto opCmp( string Op, R2 )( Expr!R2 )
     {
         return Expr!( OpBinary!( Op, R, R2 ) )();
     }
 
 So opCmp knows about the actual operator and would just use my OpBinary struct
to encode it. But this is not possible.
 
 The only workaround for I this problem I can imagine is using my own
comparison functions instead of the comparison operators:
 op!"<"( a, b ) instead of a < b.
 Another possibility would be to call opBinary explicitly:
 a.opCmp!"<"( b )
 In this case I would not even have to write additional code.
 
 But these workarounds are ugly, if would greatly prefer the normal comparison
operators.
 Does anyone has an idea how to use them?
 
 Regards,
 enuhtac

In the present language I don't think it's possible to do expression templates involving opCmp or opEquals, since you have no control over the return type. One other solution I did: I had some code where the result of the expression template was used in a mixin, so I moved the mixin outside the expression. Then I changed all the >, <, == into something else before converting it into an expression template. But this is ugly as well.
May 02 2011