Thread overview
Partial specialisation: howto? (in the right news group this time. *sigh*)
May 17, 2009
div0
May 17, 2009
Simen Kjaeraas
May 17, 2009
div0
May 17, 2009
Jason House
May 17, 2009
div0
May 17, 2009
Simen Kjaeraas
May 17, 2009
Hi Everybody,

Please have a look at the appended sucky code.

Obv. the createHandlerCode function is a pain in the back side for extending this system; I want multiple different partially specialised implementations.

So whats the syntax for doing partial specialisation?

Damed if I can work it out.

==================

enum EHandlerType {
	eMsgRangeHdlr,
	eMsgHdlr,
	eCmdIdHdlr
}

template createHandlerCode(T ...) {
	string format() {
		static if(T[0]._type == EHandlerType.eMsgRangeHdlr)
			return createMessageRangeHandler!(T).format();
		else static if(T[0]._type == EHandlerType.eMsgHdlr)
			return createMessageHandler!(T).format();
		else static if(T[0]._type == EHandlerType.eCmdIdHdlr)
			return createCommandIdHandler!(T).format();
		else
			static assert(false, "handler type not handled");
	}
}

struct msgRangeHdlr(uint msgIdFirst, uint msgIdLast, string
responseMethod) {
	invariant EHandlerType	_type = EHandlerType.eMsgRangeHdlr;
	invariant string	_msgIdFirst = std.metastrings.ToString!(msgIdFirst);
	invariant string	_msgIdLast = std.metastrings.ToString!(msgIdLast);
	invariant string 	_responseMethod = responseMethod;
}

struct msgHdlr(uint msgId, string responseMethod) {
	invariant EHandlerType	_type = EHandlerType.eMsgHdlr;
	invariant string	_msgId = std.metastrings.ToString!(msgId);
	invariant string 	_responseMethod = responseMethod;
}

struct cmdIdHdlr(uint cmdId, string responseMethod) {
	invariant EHandlerType	_type = EHandlerType.eCmdIdHdlr;
	invariant string	_cmdId = std.metastrings.ToString!(cmdId);
	invariant string 	_responseMethod = responseMethod;
}

- --
My enormous talent is exceeded only by my outrageous laziness.
May 17, 2009
div0 wrote:

It seems I might know how to do this after all.

As is mentioned under template constraints[1], templates can be specialized by trailing the parameter list with a condition:

template createHandlerCode( T... ) if ( T[0]._type == EHandlerType.eMsgRangeHdlr ) {
 string format( ) {
   return createMessageRangeHandler!( T ).format();
 }
}
template createHandlerCode( T... ) if ( T[0]._type == EHandlerType.eMsgHdlr ) {
 string format( ) {
   return createMessageHandler!( T ).format();
 }
}
template createHandlerCode( T... ) if ( T[0]._type == EHandlerType.eCmdIdHdlr ) {
 string format( ) {
   return createCommandIdHandler!( T ).format();
 }
}

This code is D2-only and untested, so there is certainly a possibility it will not work for you.

[1]: http://www.digitalmars.com/d/2.0/template.html#Constraint

--
 Simen
May 17, 2009
Thanks Simen,

That's nicer than the chained static ifs.
Is there anyway to get rid of the enum though?

Using the enum is a pain as it means you have to edit that import anytime you need to create a specialistion.

Simen Kjaeraas wrote:
> div0 wrote:
> 
> It seems I might know how to do this after all.
> 
> As is mentioned under template constraints[1], templates can be specialized by trailing the parameter list with a condition:
> 
> template createHandlerCode( T... ) if ( T[0]._type ==
> EHandlerType.eMsgRangeHdlr ) {
>  string format( ) {
>    return createMessageRangeHandler!( T ).format();
>  }
> }
> template createHandlerCode( T... ) if ( T[0]._type ==
> EHandlerType.eMsgHdlr ) {
>  string format( ) {
>    return createMessageHandler!( T ).format();
>  }
> }
> template createHandlerCode( T... ) if ( T[0]._type ==
> EHandlerType.eCmdIdHdlr ) {
>  string format( ) {
>    return createCommandIdHandler!( T ).format();
>  }
> }
> 
> This code is D2-only and untested, so there is certainly a possibility it will not work for you.
> 
> [1]: http://www.digitalmars.com/d/2.0/template.html#Constraint
> 
> -- 
>  Simen


- --
My enormous talent is exceeded only by my outrageous laziness.
May 17, 2009
div0 wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Thanks Simen,
> 
> That's nicer than the chained static ifs.
> Is there anyway to get rid of the enum though?
> 
> Using the enum is a pain as it means you have to edit that import anytime you need to create a specialistion.

It's nearly impossible to answer your question without knowing what you're trying to achieve.  For example, you're specializing on T... which means there are more template arguments.  Is there anything differentiating the cases in those?  Another candidate is a class hierarchy (or use of an interface) where createHandlerCode is defined in the base definition, and each inheriting class overrides the method.

May 17, 2009
Jason House wrote:
> div0 wrote:
> 
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Thanks Simen,
>>
>> That's nicer than the chained static ifs.
>> Is there anyway to get rid of the enum though?
>>
>> Using the enum is a pain as it means you have to edit that import anytime you need to create a specialistion.
> 
> It's nearly impossible to answer your question without knowing what you're trying to achieve.  For example, you're specializing on T... which means there are more template arguments.  Is there anything differentiating the cases in those?  Another candidate is a class hierarchy (or use of an interface) where createHandlerCode is defined in the base definition, and each inheriting class overrides the method.
> 
I've just reread it and realised I deleted too much stuff for anybody to get what I was after. doh.

But as per usual, I thought of a much easier way to do it about 10 minutes after I asked the question.

Thanks for your responses though! :)

- --
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk
May 17, 2009
div0 wrote:

> Thanks Simen,
>
> That's nicer than the chained static ifs.
> Is there anyway to get rid of the enum though?

I would believe this to work:


template createHandlerCode( T... ) if ( is( T == msgRangeHdlr ) ) {
	string format( ) {
		return createMessageRangeHandler!(T).format();
	}
}
template createHandlerCode( T... ) if ( is( T == msgHdlr ) ) {
	string format( ) {
		return createMessageHandler!(T).format();
	}
}
template createHandlerCode( T... ) if ( is( T == cmdIdHdlr ) ) {
	string format( ) {
		return createCommandIdHandler!(T).format();
	}
}

--
 Simen