www.digitalmars.com         C & C++   DMDScript  

D - Constrained Templates

reply Eric Decker <Eric_member pathlink.com> writes:
I was wondering if there is any intention of providing constrained templates. As
an example, lets say I am creating a matrix class, but I want to allow the
clients of my class to specify if the elements of the class are integers, reals,
complex numbers, etc. What I would like to be able to do is create the class and
have the type of the elements by the template parameter. Furthermore, I want to
be able to guarantee that the type for which the clients of the class are using
provide the standard set of arithmetic operators. 

There is no way to guarantee this in C++, Java, or D. An example of where this
can be done is in the Eiffel programming language. In Eiffel all classes with
the basic arithmetic operators are derived from the class NUMERIC. Furthermore,
types which have relational operators  defined are derived from the COMPARABLE
class. So, for a matrix class we would probably want to ensure that the type
specified via the client user is derived from class NUMERIC and COMPARABLE.


- Eric Decker
Feb 12 2004
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
Eric Decker wrote:
 I was wondering if there is any intention of providing constrained templates.
As
 an example, lets say I am creating a matrix class, but I want to allow the
 clients of my class to specify if the elements of the class are integers,
reals,
 complex numbers, etc. What I would like to be able to do is create the class
and
 have the type of the elements by the template parameter. Furthermore, I want to
 be able to guarantee that the type for which the clients of the class are using
 provide the standard set of arithmetic operators. 
 
 There is no way to guarantee this in C++, Java, or D. An example of where this
 can be done is in the Eiffel programming language. In Eiffel all classes with
 the basic arithmetic operators are derived from the class NUMERIC. Furthermore,
 types which have relational operators  defined are derived from the COMPARABLE
 class. So, for a matrix class we would probably want to ensure that the type
 specified via the client user is derived from class NUMERIC and COMPARABLE.
This is part and parcel with template specialization: private class MatrixProxy(T, int rows, int cols) { // General matrix definition goes here } template Matrix(T : int, int rows, int cols) { alias MatrixProxy!(T, rows, cols) Matrix; } template Matrix(T : float, int rows, int cols) { alias MatrixProxy!(T, rows, cols) Matrix; } // etc By not providing an unspecialized definition for T, the specializations become the only allowed types. This brings up a problem: Should D grow syntax explicitly for specializing for multiple types? In the above example, Matrix has to be explicitly specialized for each type. It'd be nice to be able to say something like this: template Matrix(T : (float, int, real, complex), int rows, int cols) { alias MatrixProxy!(T, rows, cols) Matrix; } -- andy
Feb 12 2004
next sibling parent Sam McCall <tunah.d tunah.net> writes:
In article <c0h6bj$2l9v$1 digitaldaemon.com>, Andy Friesen says...
Eric Decker wrote:
 I was wondering if there is any intention of providing constrained templates.
As
 an example, lets say I am creating a matrix class, but I want to allow the
 clients of my class to specify if the elements of the class are integers,
reals,
 complex numbers, etc. What I would like to be able to do is create the class
and
 have the type of the elements by the template parameter. Furthermore, I want to
 be able to guarantee that the type for which the clients of the class are using
 provide the standard set of arithmetic operators. 
 
 There is no way to guarantee this in C++, Java, or D.
You can do it in java, all the numeric classes (Integer, Double, not int, double) extend Number, so you can do class Matrix<? extends Number>. Autoboxing gives you as much primitive support as you'll ever get for templates in java. Sam
Feb 12 2004
prev sibling parent Eric Decker <Eric_member pathlink.com> writes:
In article <c0h6bj$2l9v$1 digitaldaemon.com>, Andy Friesen says...
Eric Decker wrote:
 I was wondering if there is any intention of providing constrained templates.
As
 an example, lets say I am creating a matrix class, but I want to allow the
 clients of my class to specify if the elements of the class are integers,
reals,
 complex numbers, etc. What I would like to be able to do is create the class
and
 have the type of the elements by the template parameter. Furthermore, I want to
 be able to guarantee that the type for which the clients of the class are using
 provide the standard set of arithmetic operators. 
 
 There is no way to guarantee this in C++, Java, or D. An example of where this
 can be done is in the Eiffel programming language. In Eiffel all classes with
 the basic arithmetic operators are derived from the class NUMERIC. Furthermore,
 types which have relational operators  defined are derived from the COMPARABLE
 class. So, for a matrix class we would probably want to ensure that the type
 specified via the client user is derived from class NUMERIC and COMPARABLE.
This is part and parcel with template specialization: private class MatrixProxy(T, int rows, int cols) { // General matrix definition goes here } template Matrix(T : int, int rows, int cols) { alias MatrixProxy!(T, rows, cols) Matrix; } template Matrix(T : float, int rows, int cols) { alias MatrixProxy!(T, rows, cols) Matrix; } // etc By not providing an unspecialized definition for T, the specializations become the only allowed types. This brings up a problem: Should D grow syntax explicitly for specializing for multiple types? In the above example, Matrix has to be explicitly specialized for each type. It'd be nice to be able to say something like this: template Matrix(T : (float, int, real, complex), int rows, int cols) { alias MatrixProxy!(T, rows, cols) Matrix; } -- andy
The problem with this approach is that it assumes you know all possible types that the user may want, and if one is not specified then they must add it. Assuming that you can specialize for multiple types in the manner as shown, then if later on I create a new type for handling fractions, or arbitrary precision numbers I know need to go back and modify the above code. The point of templates is to write it once, and let the compiler generate appropriate code for each type to which we apply this template pattern. We can view the role of a constrained template type to be that of contract requirement. It pinpoits what features are required. This is definitely one of the areas in which Eiffel is far superior to many other object oriented languages. Don't get me wrong, I am not actually an advocate of the Eiffel language. Eiffel has has many shortcomings but it also has many strengths including how it implements multiple inheritence, design by contract, and genericity (templates).
Feb 12 2004
prev sibling next sibling parent Sean Kelly <sean ffwd.cx> writes:
It's not perfect, but you could use the unit tests as a constraint 
mechanism.  Do a bunch of arithmetic with the instantiated template and 
if the variable type doesn't implement the required operators then 
compilation will fail.


Sean
Feb 12 2004
prev sibling next sibling parent reply "Achilleas Margaritis" <axilmar b-online.gr> writes:
In C++, if the template type does not conform to the interface as it is used
by the template, the code will not compile. Why do you need to have
constraints ?

"Eric Decker" <Eric_member pathlink.com> wrote in message
news:c0h3hm$2h5h$1 digitaldaemon.com...
 I was wondering if there is any intention of providing constrained
templates. As
 an example, lets say I am creating a matrix class, but I want to allow the
 clients of my class to specify if the elements of the class are integers,
reals,
 complex numbers, etc. What I would like to be able to do is create the
class and
 have the type of the elements by the template parameter. Furthermore, I
want to
 be able to guarantee that the type for which the clients of the class are
using
 provide the standard set of arithmetic operators.

 There is no way to guarantee this in C++, Java, or D. An example of where
this
 can be done is in the Eiffel programming language. In Eiffel all classes
with
 the basic arithmetic operators are derived from the class NUMERIC.
Furthermore,
 types which have relational operators  defined are derived from the
COMPARABLE
 class. So, for a matrix class we would probably want to ensure that the
type
 specified via the client user is derived from class NUMERIC and
COMPARABLE.
 - Eric Decker
Feb 13 2004
parent reply Matthias Becker <Matthias_member pathlink.com> writes:
In C++, if the template type does not conform to the interface as it is used
by the template, the code will not compile. Why do you need to have
constraints ?
To get "usable" messages from the compiler? Otherwise, he will show you some line deep in the library, where the template is defined, instead of the place, where the error realy is (where you instantiate the template with a wrong type).
Feb 13 2004
parent reply Sean Kelly <sean ffwd.cx> writes:
Matthias Becker wrote:
 
 To get "usable" messages from the compiler? Otherwise, he will show you some
 line deep in the library, where the template is defined, instead of the place,
 where the error realy is (where you instantiate the template with a wrong
type).
That's a compiler issue, not a language definition issue. Sean
Feb 13 2004
parent "Achilleas Margaritis" <axilmar b-online.gr> writes:
I totally agree, that's a compiler issue. Why bloat D even more ?

The compiler could have said:

"At line 15, column 0, the template instantiation with type 'Foo' is
invalid."

"Sean Kelly" <sean ffwd.cx> wrote in message
news:c0iuun$2fl6$1 digitaldaemon.com...
 Matthias Becker wrote:
 To get "usable" messages from the compiler? Otherwise, he will show you
some
 line deep in the library, where the template is defined, instead of the
place,
 where the error realy is (where you instantiate the template with a
wrong type).
 That's a compiler issue, not a language definition issue.

 Sean
Feb 14 2004
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Eric Decker" <Eric_member pathlink.com> wrote in message
news:c0h3hm$2h5h$1 digitaldaemon.com...
 I was wondering if there is any intention of providing constrained
templates. Already there: template foo(T : Bar) { ... } means that T can only be a Bar or a type derived from Bar.
Feb 13 2004
parent reply "Achilleas Margaritis" <axilmar b-online.gr> writes:
But it still doesn't solve the problem of interface conformance. What if
subclasses of Bar hide interfaces that the template needs ?

"Walter" <walter digitalmars.com> wrote in message
news:c0khog$1tu8$1 digitaldaemon.com...
 "Eric Decker" <Eric_member pathlink.com> wrote in message
 news:c0h3hm$2h5h$1 digitaldaemon.com...
 I was wondering if there is any intention of providing constrained
templates. Already there: template foo(T : Bar) { ... } means that T can only be a Bar or a type derived from Bar.
Feb 14 2004
parent "Walter" <walter digitalmars.com> writes:
It probably won't compile the template instantiation successfully.

"Achilleas Margaritis" <axilmar b-online.gr> wrote in message
news:c0ksmv$2i4s$1 digitaldaemon.com...
 But it still doesn't solve the problem of interface conformance. What if
 subclasses of Bar hide interfaces that the template needs ?

 "Walter" <walter digitalmars.com> wrote in message
 news:c0khog$1tu8$1 digitaldaemon.com...
 "Eric Decker" <Eric_member pathlink.com> wrote in message
 news:c0h3hm$2h5h$1 digitaldaemon.com...
 I was wondering if there is any intention of providing constrained
templates. Already there: template foo(T : Bar) { ... } means that T can only be a Bar or a type derived from Bar.
Feb 15 2004