Conditional Templates
Max Samukha
samukha at voliacable.com
Mon Jan 29 00:18:27 PST 2007
On Mon, 29 Jan 2007 17:28:51 +1100, Derek Parnell
<derek at nomail.afraid.org> wrote:
>Help! The D documentation makes me seem such a fool.
>
>Here is what I want to do ...
>
>I want to create a template for a single class member method that behaves
>differently depending on the type of the one parameter supplied to the
>method. In other words, if the method is called with a integer type of
>parameter, D should instantiate one form of the member method, and if the
>parameter is a floating point data type, D should instantiate another form
>of the member method, and finally if the parameter is a specific class, D
>should instantiate yet another form of the member method.
>
>So in 'pseudo' code ...
>
>class Bar
>{
> template Foo(T)
> {
> static if (T is an integer type) // byte, ubyte, short, ushort, ...
> {
> void Foo(T x)
> {
> // do something with the integer 'x'
> }
> }
>
> static if (T is a floating point type) // float, double, real
> {
> void Foo(T x)
> {
> // do something with the floating point value.
> }
> }
>
> static if (T is the class 'Bar')
> {
> void Foo(Bar x)
> {
> // do something with this object.
> }
> }
>
> // All other forms are illegal.
> }
>}
>
>I've searched the docs and failed to solve how this can be done, if at all.
>I'm sure there are some examples in the newsgroup postings but its like
>looking for something that you don't know what it actually looks like.
>
>I did note that the docs say you can't use templates to add non-static
>class members, but I tried and it works fine; so I don't know if the docs
>are wrong, I'm wrong or DMD is wrong.
With a mixin (if you want your method in more than one class):
template TFoo(T)
{
static if (is(T == float) || is(T == real))
{
void Foo(T x)
{
writefln("In float foo: ", x);
}
}
else static if (is(T == int) || is(T == short))
{
void Foo(T x)
{
writefln("In integer foo: ", x);
}
}
else static assert("Bad type");
}
class Bar(T)
{
mixin TFoo!(T);
}
void main()
{
auto bar = new Bar!(int);
bar.Foo(1);
auto bar2 = new Bar!(real);
bar2.Foo(2.345364);
}
Or directly in the class body:
class Bar(T)
{
static if (is(T == float) || is(T == real))
{
void Foo(T x)
{
writefln("In float foo: ", x);
}
}
else static if (is(T == int) || is(T == short))
{
void Foo(T x)
{
writefln("In integer foo: ", x);
}
}
else static assert("Bad type");
}
void main()
{
auto bar = new Bar!(int);
bar.Foo(1);
auto bar2 = new Bar!(real);
bar2.Foo(2.345364);
}
You can also turn 'is' conditions into templates (I'm not sure if they
are in the std library already)
template IsFloat(T)
{
const bool IsFloat = is(T == float) || is(T == double) || ...;
}
and use it like this: static if (IsFloat!(T)) ...
You could also try to put 'static if' in the method's body, which is
cleaner:
...
void Foo(T x)
{
static if ()
{
}
else static if () ...
}
More information about the Digitalmars-d-learn
mailing list