Thread overview
Extending Template Specialization
Aug 16, 2005
John C
Aug 16, 2005
Chris Sauls
Aug 16, 2005
John C
August 16, 2005
The upcoming C# 2.0 (as well as C++/CLI and VB.NET) has added a useful facility to its template implementation to allow you to apply restrictions on type parameters, called constraints. Here's an example:

    class MyValue<T> where T : struct {
    }

This tells the compiler only to instantiate MyValue for structs (and primitive types such as int and long).

In D, we can already specialize templates based on type, but it would be good to be able to extend specialization to restrict the type of type, so to speak, perhaps similar to how the recently introduced IsExpressions work. At compile time, the compiler would issue an error if code tries to instantiate a template with a type that is not permitted by the template's (optional) constraints. This facility would be useful, for example, if a template relies on value semantics (ie, it expects a struct), or it relies on class sematics (eg, it returns "null").

I think we can get away without adding any keywords to the language (constraints-supporting .NET languages added "where"). The syntax might look like this:

    struct MyValue(T : struct) {
    }

Other constraints allowed would include the same range allowed for IsExpressions, eg:

    template MyTemplate(T : class)
    template MyTemplate(T : enum)
    template MyTemplate(T : interface)

and so on. Another might be to enfore that the type has a default constructor:

    template MyTemplate(T : new())

Today I have to provide a default implementation of a template, and then specialize it for types I don't want to allow. Constraints would do the reverse, and would be an elegant addition.

Do people have ideas for how this might be done today, maybe with IsExpressions? And do people think this is a good idea?

John.


August 16, 2005
John C wrote:
> The upcoming C# 2.0 (as well as C++/CLI and VB.NET) has added a useful facility to its template implementation to allow you to apply restrictions on type parameters, called constraints. Here's an example:
> 
>     class MyValue<T> where T : struct {
>     }
> 
> This tells the compiler only to instantiate MyValue for structs (and primitive types such as int and long).
> 
> In D, we can already specialize templates based on type, but it would be good to be able to extend specialization to restrict the type of type, so to speak, perhaps similar to how the recently introduced IsExpressions work.

I definitely agree, andI vaguely recall some mention from Walter that something like this is in the works.  But I thought I'd chime in anyway.

In the Lux project (Lux is a concept-language that's been "in development" for about as long as D has, but without the ferverous community to drive it) we have this kind of specialization, based on "type attributes".  A given template parameter can specialize via a "filter" that "requires", "includes", and "excludes" specified attributes.  (These filters actually define attributes and can be applied to functions/methods as well, for customized protection.)

Example: for a template Foo that behaves differently for classes and structs, and doesn't want any other types, in Lux:

# define template Foo (
#   filter(require(class)) symbol T
# ) {
#   // do stuff
# }
#
# define template Foo (
#   filter(require(struct)) symbol T
# ) {
#   // do stuff
# }

Now, I don't neccessarily recommend the "filter" mechanism in D.  I imagine it'd be a load of trouble to implement.  However, I do think the "attributes" concept might have some validity.  Maybe something like:

# // in D
# template Foo (alias T : @class) {
#   // do stuff
# }
#
# template Foo (alias T : @struct) {
#   // do stuff
# }

I figure '$' could be used as well, even though it has the other meaning of "length of current array".  I don't see how this usage could possibly get confused with that one, but I suppose that might add a parsing quirk.

-- Chris Sauls
August 16, 2005
"Chris Sauls" <ibisbasenji@gmail.com> wrote in message news:ddtcqv$qql$1@digitaldaemon.com...
>
> I definitely agree, andI vaguely recall some mention from Walter that something like this is in the works.  But I thought I'd chime in anyway.

That's good to hear.

>
> In the Lux project (Lux is a concept-language that's been "in development" for about as long as D has, but without the ferverous community to drive it) we have this kind of specialization, based on "type attributes".  A given template parameter can specialize via a "filter" that "requires", "includes", and "excludes" specified attributes.  (These filters actually define attributes and can be applied to functions/methods as well, for customized protection.)
>
> Example: for a template Foo that behaves differently for classes and structs, and doesn't want any other types, in Lux:
>
> # define template Foo (
> #   filter(require(class)) symbol T
> # ) {
> #   // do stuff
> # }
> #
> # define template Foo (
> #   filter(require(struct)) symbol T
> # ) {
> #   // do stuff
> # }
>
> Now, I don't neccessarily recommend the "filter" mechanism in D.  I imagine it'd be a load of trouble to implement.  However, I do think the "attributes" concept might have some validity.  Maybe something like:
>
> # // in D
> # template Foo (alias T : @class) {
> #   // do stuff
> # }
> #
> # template Foo (alias T : @struct) {
> #   // do stuff
> # }
>
> I figure '$' could be used as well, even though it has the other meaning of "length of current array".  I don't see how this usage could possibly get confused with that one, but I suppose that might add a parsing quirk.
>
> -- Chris Sauls

I too would like to see custom attributes added to the language, ala Java's new annotations. Wouldn't D need deeper RTTI or introspection to make custom attributes useful? Otherwise I can't see how you'd apply attributes to user code (C#, for instance, uses reflection to achieve this).