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