diff -u8 dmd_/expression.c dmd/expression.c
--- dmd_/expression.c	2006-11-25 19:17:48.000000000 +0900
+++ dmd/expression.c	2006-11-30 19:07:29.000000000 +0900
@@ -5425,17 +5425,17 @@
 {
     buf->writestring("delete ");
     expToCBuffer(buf, hgs, e1, precedence[op]);
 }
 
 /************************************************************/
 
 CastExp::CastExp(Loc loc, Expression *e, Type *t)
-	: UnaExp(loc, TOKcast, sizeof(CastExp), e)
+	: BinExp(loc, TOKcast, sizeof(CastExp), e, new TypeExp(loc, t))
 {
     to = t;
 }
 
 Expression *CastExp::syntaxCopy()
 {
     return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy());
 }
@@ -5449,17 +5449,17 @@
 #if LOGSEMANTIC
     printf("CastExp::semantic('%s')\n", toChars());
 #endif
 
 //static int x; assert(++x < 10);
 
     if (type)
 	return this;
-    UnaExp::semantic(sc);
+    BinExp::semantic(sc);
     if (e1->type)		// if not a tuple
     {
 	e1 = resolveProperties(sc, e1);
 	to = to->semantic(loc, sc);
 
 	e = op_overload(sc);
 	if (e)
 	{
diff -u8 dmd_/expression.h dmd/expression.h
--- dmd_/expression.h	2006-11-25 19:17:48.000000000 +0900
+++ dmd/expression.h	2006-11-30 19:08:22.000000000 +0900
@@ -793,32 +793,33 @@
     DeleteExp(Loc loc, Expression *e);
     Expression *semantic(Scope *sc);
     Expression *checkToBoolean();
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     elem *toElem(IRState *irs);
 };
 
-struct CastExp : UnaExp
+struct CastExp : BinExp
 {
     // Possible to cast to one type while painting to another type
     Type *to;			// type to cast to
 
     CastExp(Loc loc, Expression *e, Type *t);
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
     Expression *optimize(int result);
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Expression *constFold();
     elem *toElem(IRState *irs);
 
     // For operator overloading
     Identifier *opId();
+    Identifier *opId_r();
 };
 
 
 struct SliceExp : UnaExp
 {
     Expression *upr;		// NULL if implicit 0
     Expression *lwr;		// NULL if implicit [length - 1]
     VarDeclaration *lengthVar;
diff -u8 dmd_/idgen.c dmd/idgen.c
--- dmd_/idgen.c	2006-11-25 19:17:48.000000000 +0900
+++ dmd/idgen.c	2006-11-30 19:09:52.000000000 +0900
@@ -172,16 +172,17 @@
     { "postinc", "opPostInc" },
     { "postdec", "opPostDec" },
     { "index",	 "opIndex" },
     { "indexass", "opIndexAssign" },
     { "slice",	 "opSlice" },
     { "sliceass", "opSliceAssign" },
     { "call",	 "opCall" },
     { "cast",	 "opCast" },
+    { "cast_r",	 "opCast_r" },
     { "match",	 "opMatch" },
     { "next",	 "opNext" },
     { "opIn" },
     { "opIn_r" },
 
     { "classNew", "new" },
     { "classDelete", "delete" },
 
diff -u8 dmd_/opover.c dmd/opover.c
--- dmd_/opover.c	2006-11-25 19:17:48.000000000 +0900
+++ dmd/opover.c	2006-12-01 21:18:24.000000000 +0900
@@ -30,20 +30,21 @@
 #include "mtype.h"
 #include "init.h"
 #include "expression.h"
 #include "id.h"
 #include "declaration.h"
 #include "aggregate.h"
 #include "template.h"
 
-static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id);
+static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id, TemplateInstance *tempinst);
 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments);
 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments);
+static TemplateInstance *templateResolve2(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments);
 
 /******************************** Expression **************************/
 
 
 /***********************************
  * Determine if operands of binary op can be reversed
  * to fit operator overload.
  */
@@ -77,16 +78,17 @@
 
 Identifier *UAddExp::opId()   { return Id::uadd; }
 
 Identifier *NegExp::opId()   { return Id::neg; }
 
 Identifier *ComExp::opId()   { return Id::com; }
 
 Identifier *CastExp::opId()   { return Id::cast; }
+Identifier *CastExp::opId_r()   { return Id::cast_r; }
 
 Identifier *InExp::opId()     { return Id::opIn; }
 Identifier *InExp::opId_r()     { return Id::opIn_r; }
 
 Identifier *PostIncExp::opId() { return Id::postinc; }
 
 Identifier *PostDecExp::opId() { return Id::postdec; }
 
@@ -187,17 +189,17 @@
 		e = new DotIdExp(loc, e1, fd->ident);
 		e = new CallExp(loc, e, ae->arguments);
 		e = e->semantic(sc);
 		return e;
 	    }
 	    else
 	    {
 		// Rewrite +e1 as e1.add()
-		return build_overload(loc, sc, e1, NULL, fd->ident);
+		return build_overload(loc, sc, e1, NULL, fd->ident, NULL);
 	    }
 	}
     }
     return NULL;
 }
 
 
 Expression *BinExp::op_overload(Scope *sc)
@@ -208,16 +210,20 @@
     Type *t1 = e1->type->toBasetype();
     Type *t2 = e2->type->toBasetype();
     Identifier *id = opId();
     Identifier *id_r = opId_r();
 
     Match m;
     Expressions args1;
     Expressions args2;
+    Objects targs1;
+    Objects targs2;
+    TemplateInstance *tempinst1;
+    TemplateInstance *tempinst2;
     int argsset = 0;
 
     AggregateDeclaration *ad1;
     if (t1->ty == Tclass)
 	ad1 = ((TypeClass *)t1)->sym;
     else if (t1->ty == Tstruct)
 	ad1 = ((TypeStruct *)t1)->sym;
     else
@@ -249,50 +255,72 @@
 	/* Try:
 	 *	a.opfunc(b)
 	 *	b.opfunc_r(a)
 	 * and see which is better.
 	 */
 	Expression *e;
 	FuncDeclaration *lastf;
 
-	args1.setDim(1);
-	args1.data[0] = (void*) e1;
-	args2.setDim(1);
-	args2.data[0] = (void*) e2;
+	if(e1->op == TOKtype)
+	{
+	    targs1.setDim(1);
+	    targs1.data[0] = (void*) t1;
+	}
+	else
+	{
+	    args1.setDim(1);
+	    args1.data[0] = (void*) e1;
+	}
+	if(e2->op == TOKtype)
+	{
+	    targs2.setDim(1);
+	    targs2.data[0] = (void*) t2;
+	}
+	else
+	{
+	    args2.setDim(1);
+	    args2.data[0] = (void*) e2;
+	}
 	argsset = 1;
 
 	memset(&m, 0, sizeof(m));
 	m.last = MATCHnomatch;
 
 	if (s)
 	{
 	    fd = s->isFuncDeclaration();
 	    if (fd)
 	    {
 		overloadResolveX(&m, fd, &args2);
 	    }
 	    else
 	    {   td = s->isTemplateDeclaration();
-		templateResolve(&m, td, sc, loc, NULL, &args2);
+		if(e2->op != TOKtype)
+		    templateResolve(&m, td, sc, loc, NULL, &args2);
+		else
+		    tempinst2 = templateResolve2(&m, td, sc, loc, &targs2, NULL);
 	    }
 	}
 	
 	lastf = m.lastf;
 
 	if (s_r)
 	{
 	    fd = s_r->isFuncDeclaration();
 	    if (fd)
 	    {
 		overloadResolveX(&m, fd, &args1);
 	    }
 	    else
 	    {   td = s_r->isTemplateDeclaration();
-		templateResolve(&m, td, sc, loc, NULL, &args1);
+		if(e1->op != TOKtype)
+		    templateResolve(&m, td, sc, loc, NULL, &args1);
+		else
+		    tempinst1 = templateResolve2(&m, td, sc, loc, &targs1, NULL);
 	    }
 	}
 
 	if (m.count > 1)
 	{
 	    // Error, ambiguous
 	    error("overloads %s and %s both match argument list for %s",
 		    m.lastf->type->toChars(),
@@ -304,23 +332,35 @@
 	    m.lastf = m.anyf;
 	}
 
 	if (op == TOKplusplus || op == TOKminusminus)
 	    // Kludge because operator overloading regards e++ and e--
 	    // as unary, but it's implemented as a binary.
 	    // Rewrite (e1 ++ e2) as e1.postinc()
 	    // Rewrite (e1 -- e2) as e1.postdec()
-	    e = build_overload(loc, sc, e1, NULL, id);
+	    e = build_overload(loc, sc, e1, NULL, id, NULL);
 	else if (lastf && m.lastf == lastf || m.last == MATCHnomatch)
-	    // Rewrite (e1 op e2) as e1.opfunc(e2)
-	    e = build_overload(loc, sc, e1, e2, id);
+	{
+	    if(e2->op == TOKtype)
+		// Rewrite (e1 op e2) as e1.opfunc!(e2)()
+		e = build_overload(loc, sc, e1, NULL, id, tempinst2);
+	    else
+		// Rewrite (e1 op e2) as e1.opfunc(e2)
+		e = build_overload(loc, sc, e1, e2, id, NULL);
+	}
 	else
-	    // Rewrite (e1 op e2) as e2.opfunc_r(e1)
-	    e = build_overload(loc, sc, e2, e1, id_r);
+	{
+	    if(e1->op == TOKtype)
+		// Rewrite (e1 op e2) as e2.opfunc_r!(e1)()
+		e = build_overload(loc, sc, e2, NULL, id, tempinst1);
+	    else
+		// Rewrite (e1 op e2) as e2.opfunc_r(e1)
+		e = build_overload(loc, sc, e2, e1, id_r, NULL);
+	}
 	return e;
     }
 
     if (isCommutative())
     {
 	s = NULL;
 	s_r = NULL;
 	if (ad1 && id_r)
@@ -338,49 +378,72 @@
 	     *	a.opfunc_r(b)
 	     *	b.opfunc(a)
 	     * and see which is better.
 	     */
 	    Expression *e;
 	    FuncDeclaration *lastf;
 
 	    if (!argsset)
-	    {	args1.setDim(1);
-		args1.data[0] = (void*) e1;
-		args2.setDim(1);
-		args2.data[0] = (void*) e2;
+	    {
+		if(e1->op == TOKtype)
+		{
+		    targs1.setDim(1);
+		    targs1.data[0] = (void*) t1;
+		}
+		else
+		{
+		    args1.setDim(1);
+		    args1.data[0] = (void*) e1;
+		}
+		if(e2->op == TOKtype)
+		{
+		    targs2.setDim(1);
+		    targs2.data[0] = (void*) t2;
+		}
+		else
+		{
+		    args2.setDim(1);
+		    args2.data[0] = (void*) e2;
+		}
 	    }
 
 	    memset(&m, 0, sizeof(m));
 	    m.last = MATCHnomatch;
 
 	    if (s_r)
 	    {
 		fd = s_r->isFuncDeclaration();
 		if (fd)
 		{
 		    overloadResolveX(&m, fd, &args2);
 		}
 		else
 		{   td = s_r->isTemplateDeclaration();
-		    templateResolve(&m, td, sc, loc, NULL, &args2);
+		    if(e2->op != TOKtype)
+			templateResolve(&m, td, sc, loc, NULL, &args2);
+		    else
+			tempinst2 = templateResolve2(&m, td, sc, loc, &targs2, NULL);
 		}
 	    }
 	    lastf = m.lastf;
 
 	    if (s)
 	    {
 		fd = s->isFuncDeclaration();
 		if (fd)
 		{
 		    overloadResolveX(&m, fd, &args1);
 		}
 		else
 		{   td = s->isTemplateDeclaration();
-		    templateResolve(&m, td, sc, loc, NULL, &args1);
+		    if(e1->op != TOKtype)
+			templateResolve(&m, td, sc, loc, NULL, &args1);
+		    else
+			tempinst1 = templateResolve2(&m, td, sc, loc, &targs1, NULL);
 		}
 	    }
 
 	    if (m.count > 1)
 	    {
 		// Error, ambiguous
 		error("overloads %s and %s both match argument list for %s",
 			m.lastf->type->toChars(),
@@ -389,21 +452,33 @@
 	    }
 	    else if (m.last == MATCHnomatch)
 	    {
 		m.lastf = m.anyf;
 	    }
 
 	    if (lastf && m.lastf == lastf ||
 		id_r && m.last == MATCHnomatch)
-		// Rewrite (e1 op e2) as e1.opfunc_r(e2)
-		e = build_overload(loc, sc, e1, e2, id_r);
+	    {
+		if(e2->op == TOKtype)
+		    // Rewrite (e1 op e2) as e1.opfunc_r!(e2)()
+		    e = build_overload(loc, sc, e1, NULL, id_r, tempinst2);
+		else
+		    // Rewrite (e1 op e2) as e1.opfunc_r(e2)
+		    e = build_overload(loc, sc, e1, e2, id_r, NULL);
+	    }
 	    else
-		// Rewrite (e1 op e2) as e2.opfunc(e1)
-		e = build_overload(loc, sc, e2, e1, id);
+	    {
+		if(e1->op == TOKtype)
+		    // Rewrite (e1 op e2) as e2.opfunc!(e1)()
+		    e = build_overload(loc, sc, e2, NULL, id, tempinst1);
+		else
+		    // Rewrite (e1 op e2) as e2.opfunc(e1)
+		    e = build_overload(loc, sc, e2, e1, id, NULL);
+	    }
 
 	    // When reversing operands of comparison operators,
 	    // need to reverse the sense of the op
 	    switch (op)
 	    {
 		case TOKlt:	op = TOKgt;	break;
 		case TOKgt:	op = TOKlt;	break;
 		case TOKle:	op = TOKge;	break;
@@ -429,24 +504,28 @@
 
     return NULL;
 }
 
 /***********************************
  * Utility to build a function call out of this reference and argument.
  */
 
-static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
+static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id, TemplateInstance *tempinst)
 {
     Expression *e;
 
     //printf("build_overload(id = '%s')\n", id->toChars());
     //earg->print();
     //earg->type->print();
-    e = new DotIdExp(loc, ethis, id);
+
+    if (tempinst)
+	e = new DotTemplateInstanceExp(loc, ethis, tempinst);
+    else
+	e = new DotIdExp(loc, ethis, id);
 
     if (earg)
 	e = new CallExp(loc, e, earg);
     else
 	e = new CallExp(loc, e);
 
     e = e->semantic(sc);
     return e;
@@ -722,8 +801,24 @@
     else
     {
 	m->last = MATCHexact;
 	m->lastf = fd;
 	m->count = 1;
     }
 }
 
+static TemplateInstance *templateResolve2(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments)
+{
+    FuncDeclaration *fd;
+    TemplateInstance *tempinst;
+
+    assert(td);
+    tempinst = new TemplateInstance(loc, td, targsi);
+    if (!tempinst)
+	return NULL;
+    tempinst->semantic(sc);
+    fd = tempinst->toAlias()->isFuncDeclaration();
+    if (!fd)
+	return NULL;
+    overloadResolveX(m, fd, arguments);
+    return tempinst;
+}

