Partial template function specialization
Lars T. Kyllingstad
public at kyllingen.NOSPAMnet
Thu Aug 20 03:46:20 PDT 2009
Peter Alexander wrote:
> Hey all,
>
> I'm considering learning D at the moment, and one thing that has bothered me in C++ is the lack of partial template function specializations. For example, you can create something like this:
>
> template <class Field, class V>
> const Field norm(const V& v);
>
> and you can specialize it:
>
> template <>
> const double norm(const double& d)
> { return d < 0.0 ? -d : d; }
>
> but you can't partially specialize it:
>
> template <class Field>
> const Field norm(const Vector3<Field>& v)
> { /* return sqrt( ... ) */ }
>
> Unless I'm mistaken...
You've come to the right place. D's template specialisation is very
powerful, and when combined with implicit function template
instantiation (IFTI) it makes for really beautiful code.
Disclaimer: You didn't say whether you use D1 or D2, but I use D2, so
I'll give my answer in D2 code. It is highly likely it will also work in D1.
First of all, I don't know how it is in C++, but in D you rarely write
function declarations without definitions. So unless you have a very
general function body for your "general case", I'd simply drop it. If
you have, the general case looks like this:
Field norm(Field, V)(ref V v) { ... }
// To call it:
SomeDoublePrecisionVector v = ...;
double n = norm!(double, SomeDoublePrecisionVector)(v);
Actually, because of IFTI, you can probably call it like
double n = norm!(double)(v);
but there is a chance that the compiler will find it too much like the
partially specialised case below.
The completely specialised case will look like this:
double norm()(double d)
{
return d < 0.0 ? -d : d;
}
// To call it:
double n = norm(-3.0);
Note that in the not-too-far future it is likely that non-templated
functions will be allowed to overload against templated functions. When
that happens, you can drop the first set of parentheses in the declaration.
I would write the partially specialised case like this:
Field norm(Field)(ref Vector3!(Field) v) { ... }
// To call it:
Vector3!(real) myVector;
real n = norm(myVector);
Yes, the compiler is smart enough to extract the Field from the
Vector3!(Field) type. :) Because of IFTI you don't even have to specify
it when calling norm().
In the above I have at least tried to stay D1 compatible. In D2 you can
(arguably, of course) beautify your code a bit by writing Vector3!Float
and so on. The parentheses are only needed when there are several
template parameters.
For more info, check out http://www.digitalmars.com/d/2.0/template.html
-Lars
More information about the Digitalmars-d-learn
mailing list