www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Extending Template Specialization

reply "John C" <johnch_atms hotmail.com> writes:
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. 
Aug 16 2005
parent reply Chris Sauls <ibisbasenji gmail.com> writes:
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
Aug 16 2005
parent "John C" <johnch_atms hotmail.com> writes:
"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).
Aug 16 2005