Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
November 11, 2006 generalising template specialisation | ||||
---|---|---|---|---|
| ||||
Attachments: | I am going to use TemplateTypeParameterSpecialization in the samples below, all the ideas apply to TemplateValueParameterSpecialization too. Current specialisation: # # template A (T : SomeType) { /* ... */ } # Template A matches if T is implicitly convertible to SomeType. How do you define a template that matches if T is a struct? # # template B (T) { # static if(is(T == struct)) { # /* ... */ # } else { # static assert(0, "use a struct"); # } # } # OK that works, though the error will be reported on the assert line instead of the instantiation line. Now suppose someoneelse writes a template with the same functionality that supports classes: # # template B (T) { # static if(is(T == class)) { # /* ... */ # } else { # static assert(0, "use a class"); # } # } # Err, won't work: b2.d(1): template b2.B(T) conflicts with b1.B(T) at b1.d(1) Solution 1: merge those templates # # template B (T) { # static if(is(T == class)) { # /* ... */ # } else if(is(T == struct)) { # /* ... */ # } else { # static assert(0, "use a class or struct"); # } # } # Problem: Merging 2 templates having different licenses and maintainers can become a nightmare. Solution 2: use a meta template # # private import b1, b2; # # template B (T) { # static if(is(T == class)) { # alias b1.B!(T) B; # } else if(is(T == struct)) { # alias b2.B!(T) B; # } else { # static assert(0, "use a class or struct"); # } # } # Problem: This is a very brittle approach introducing an extra level of indirection and will fail if someone writes a third template supporting e.g. delegates. Please lift the current limitation and support all constructs allowed by StaticIfCondition in TemplateTypeParameterSpecialization too. Rewriting the B templates: # # template B( T : is(T == class)) { # /* ... */ # } # # template B( T : is(T == struct)) { # /* ... */ # } # I'm not aware of any lexicographic issues or problems with existing code. Thomas |
November 11, 2006 Re: generalising template specialisation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne | Thomas Kuehne wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> I am going to use TemplateTypeParameterSpecialization in the samples
> below, all the ideas apply to TemplateValueParameterSpecialization too.
>
>
> Current specialisation:
> #
> # template A (T : SomeType) { /* ... */ }
> #
>
> Template A matches if T is implicitly convertible to SomeType.
>
>
> How do you define a template that matches if T is a struct?
> #
> # template B (T) {
> # static if(is(T == struct)) {
> # /* ... */
> # } else {
> # static assert(0, "use a struct");
> # }
> # }
> #
>
> OK that works, though the error will be reported on the assert line
> instead of the instantiation line.
This is where concept checking is really useful. However, you can overload on concepts in D using something like the following:
struct ClassType {}
struct StructType {}
...
template TypeOf( T ) {
static if( is( T == class ) )
alias ClassType TypeOf;
else static if( is( T == struct ) )
alias StructType TypeOf;
...
}
template ClassTempl( T, Type : ClassType = TypeOf!(T) ) {
// make sure the user didn't cheat
static assert( is( Type == TypeOf!(T) );
...
}
template StructTempl( T Type : StructType = TypeOf!(T) ) {
// make sure the user didn't cheat
static assert( is( Type == TypeOf!(T) );
...
}
It's a bit messy, but it works.
Sean
|
November 12, 2006 Re: generalising template specialisation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne | Thomas Kuehne wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> I am going to use TemplateTypeParameterSpecialization in the samples
> below, all the ideas apply to TemplateValueParameterSpecialization too.
>
>
> Current specialisation:
> #
> # template A (T : SomeType) { /* ... */ }
> #
>
> Template A matches if T is implicitly convertible to SomeType.
>
>
> How do you define a template that matches if T is a struct?
> #
> # template B (T) {
> # static if(is(T == struct)) {
> # /* ... */
> # } else {
> # static assert(0, "use a struct");
> # }
> # }
> #
>
> OK that works, though the error will be reported on the assert line
> instead of the instantiation line. Now suppose someoneelse writes a
> template with the same functionality that supports classes:
>
> #
> # template B (T) {
> # static if(is(T == class)) {
> # /* ... */
> # } else {
> # static assert(0, "use a class");
> # }
> # }
> #
>
> Err, won't work:
> b2.d(1): template b2.B(T) conflicts with b1.B(T) at b1.d(1)
>
> Solution 1: merge those templates
> #
> # template B (T) {
> # static if(is(T == class)) {
> # /* ... */
> # } else if(is(T == struct)) {
> # /* ... */
> # } else {
> # static assert(0, "use a class or struct");
> # }
> # }
> #
>
> Problem: Merging 2 templates having different licenses and maintainers
> can become a nightmare.
>
> Solution 2: use a meta template
> #
> # private import b1, b2;
> #
> # template B (T) {
> # static if(is(T == class)) {
> # alias b1.B!(T) B;
> # } else if(is(T == struct)) {
> # alias b2.B!(T) B;
> # } else {
> # static assert(0, "use a class or struct");
> # }
> # }
> #
>
> Problem: This is a very brittle approach introducing an extra level
> of indirection and will fail if someone writes a third template
> supporting e.g. delegates.
>
> Please lift the current limitation and support all constructs allowed by
> StaticIfCondition in TemplateTypeParameterSpecialization too.
>
> Rewriting the B templates:
> #
> # template B( T : is(T == class)) {
> # /* ... */
> # }
> #
> # template B( T : is(T == struct)) {
> # /* ... */
> # }
> #
>
> I'm not aware of any lexicographic issues or problems with existing
> code.
>
> Thomas
+1.
Don't have much to add, but I agree that for serious libraries, 3rd party code needs to be able to add new specializations without modifying the source of the original.
--bb
|
November 12, 2006 Re: generalising template specialisation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne | Thomas Kuehne wrote:
>
> Please lift the current limitation and support all constructs allowed by
> StaticIfCondition in TemplateTypeParameterSpecialization too.
>
> Rewriting the B templates:
> #
> # template B( T : is(T == class)) {
> # /* ... */
> # }
> #
> # template B( T : is(T == struct)) {
> # /* ... */
> # }
> #
By the way, in case it didn't seem like it in my other post, I would *love* to have a feature like this. It would be a reasonable substitute for concept checking in D.
Sean
|
November 12, 2006 Re: generalising template specialisation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne | On Sat, 11 Nov 2006 18:31:02 +0200, Thomas Kuehne <thomas-dloop@kuehne.cn> wrote:
> Please lift the current limitation and support all constructs allowed by
> StaticIfCondition in TemplateTypeParameterSpecialization too.
>
> Rewriting the B templates:
> #
> # template B( T : is(T == class)) {
> # /* ... */
> # }
> #
> # template B( T : is(T == struct)) {
> # /* ... */
> # }
> #
I fully agree.
|
Copyright © 1999-2021 by the D Language Foundation