how to properly overload function templates?

Steven Schveighoffer schveiguy at yahoo.com
Fri Mar 12 05:22:03 PST 2010


On Thu, 11 Mar 2010 19:15:37 -0500, Trass3r <un at known.com> wrote:

> I stumbled across this while playing with operator overloading. Since  
> they are now function templates, this becomes an issue.
>
> struct Vector2(T)
> {
> 	T x;
> 	T y;
>
> 	/// element-wise operations, +, -,
> 	Vector2 opBinary(string op)(ref Vector2 v)
> 	{
> 		mixin("return Vector2!(T)( cast(T)(x " ~ op ~ " v.x), cast(T)(y " ~ op  
> ~ " v.y) );");
> 	}
>
> 	/// operation with scalar
> 	Vector2 opBinary(string op)(int i)
> 	{
> 		mixin("return Vector2!(T) ( cast(T)(x " ~ op ~ " i), cast(T)(y " ~ op  
> ~ " i) );");
> 	}
> }
>
> This yields:
> template instance opBinary!("+") matches more than one template  
> declaration
>
> Of course this can be circumvented by using
> opBinary(string op, U:Vector2)(U v)
> opBinary(string op, U:int)(U v)
>
>
> But is this how it's supposed to be done? Couldn't the compiler detect  
> that itself?

The issue is with two things.

First, there are two instantiations of the template.  You have to realize  
that a template is somewhat of a namespace, and they do not append to  
eachother.  Think about it this way, a template function is really a  
shortcut for this:

template fn(T)
{
     fn(args) {...}
}

So what you have done is:

template fn(T)
{
    fn(args1) {...}
}

template fn(T)
{
    fn(args2) {...}
}

The compiler doesn't combine the two templates together, so it doesn't  
know which namespace you are talking about.

I tried something like this:

template fn(T)
{
    fn(args1) {...}
    fn(args2) {...}
}

but this doesn't work, because the compiler refuses to call the function  
via fn!(T)(args1).

I think the only option you are faced with at the moment is to include the  
argument type in the template specification, thereby separating the  
namespace.

You should file a bug on this.  I think it's not a good result of the new  
operator overloading regime.  However, I think it can be fixed, by either  
handling template function overloads, or having the compiler rewrite

x + b

as

x.opBinary!("+").opBinary(b);

since we aren't even using IFTI here.  Then my proposed overloaded  
template functions will work.

-Steve


More information about the Digitalmars-d-learn mailing list