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