D - Constrained Genericity (template suggestion)
- reiter nomadics.com (Mac Reiter) (67/67) Jan 22 2002 One of the things I really like about the genericity/template system
- OddesE (15/82) Jan 22 2002 I was thinking of something else that looks a lot like what you are
One of the things I really like about the genericity/template system
in Eiffel is so-called "Constrained Genericity". For the full
description, you can probably find information at www.eiffel.com or in
"Object Oriented Software Construction, 2nd Edition" (otherwise known
as OOSC2), but an extremely short example, converted to C++'ish syntax
would be:
template <typename T:SORTABLE> T max(T a, T b)
{
return a<b ? b : a;
}
The only non-C++ code I meant to be present in the preceding code is
the use of "typename T:SORTABLE" instead of just "typename T". (If I
got anything else wrong, it is just a typo, and not significant) This
mechanism can also be applied to template classes (which is the
primary use of it in Eiffel), but the max() example is shorter and
simpler.
What this means is that this template can only be instantiated with
types that are SORTABLE or are derived from SORTABLE. Since max()
uses operator< on type T, we need to know that type T supports
operator<. C++ does this at the point of call, which is OK as far as
it goes, but the above syntax has a few advantages:
1. What a type IS is more than just the collection of available
operators. In the example, SORTABLE specifically means that operator<
provides a total ordering (I can't remember strong/weak definitions,
so I leave them out of this). Other types may have operator< that
doesn't provide a total ordering, and would not derive from SORTABLE,
and would not be appropriate for use here, even though C++ would
compile it.
2. Because the constraints appear in the declaration of the template,
users of max() know that they can only use it on types that are
SORTABLE. Self-documenting code is good...
3. Because the relevant interface is in the declaration, it *should*
be easier for compilers to provide more direct and meaningful error
messages. I prefer "Error : templatized type T in max() must be of
type SORTABLE." over "Error : operator< is not defined for type
FLEEM". This may just be a personal style kind of thing.
I seem to remember that you can use the "like" keyword to introduce
covariance constraints, as well. For example, the previous template
could also be written as:
template <typename T1:SORTABLE, T2:like T1> T1 max(T1 a, T2 b)
{
return a<b ? b : a;
}
The primary addition here is the second parameterized/templatized
type, which is also constrained, but is constrained to be "like" the
first type (T1). This means that T2 can be the same as T1, or it can
be any type derived from T1 (I think -- sorry, my Eiffel is a little
rusty). This is not especially meaningful for max(), but it can be
very useful for properly expressing constraints on generic classes
that need to manipulate different types, but need those types to have
specific relationships to each other.
I gave the above template form because Eiffel uses the "like" keyword,
but it looks unnecessary (and is, in that context). After all, the
declaration could just be:
template <typename T1:SORTABLE, T2:T1> T1 max(T1 a, T2 b)
and it would mean exactly the same thing (T2 is of type T1 or is
derived from T1). The "like" keyword is generally used inside
templatized classes to add members that are constrained to be "like"
one of the templatized types.
I have wandered, and I need to go read OOSC2 again, but the central
point (for those of you with the patience to put up with me this far)
is that Constrained Genericity and Type Covariance are useful
constructs that do not exist in C++ (without some painful twisting
around) and that I would like to see added to D.
Thank you for your time and consideration,
Mac Reiter
Software Engineer
Jan 22 2002
"Mac Reiter" <reiter nomadics.com> wrote in message
news:3c4d7a82.405408206 news.digitalmars.com...
One of the things I really like about the genericity/template system
in Eiffel is so-called "Constrained Genericity". For the full
description, you can probably find information at www.eiffel.com or in
"Object Oriented Software Construction, 2nd Edition" (otherwise known
as OOSC2), but an extremely short example, converted to C++'ish syntax
would be:
template <typename T:SORTABLE> T max(T a, T b)
{
return a<b ? b : a;
}
The only non-C++ code I meant to be present in the preceding code is
the use of "typename T:SORTABLE" instead of just "typename T". (If I
got anything else wrong, it is just a typo, and not significant) This
mechanism can also be applied to template classes (which is the
primary use of it in Eiffel), but the max() example is shorter and
simpler.
What this means is that this template can only be instantiated with
types that are SORTABLE or are derived from SORTABLE. Since max()
uses operator< on type T, we need to know that type T supports
operator<. C++ does this at the point of call, which is OK as far as
it goes, but the above syntax has a few advantages:
1. What a type IS is more than just the collection of available
operators. In the example, SORTABLE specifically means that operator<
provides a total ordering (I can't remember strong/weak definitions,
so I leave them out of this). Other types may have operator< that
doesn't provide a total ordering, and would not derive from SORTABLE,
and would not be appropriate for use here, even though C++ would
compile it.
2. Because the constraints appear in the declaration of the template,
users of max() know that they can only use it on types that are
SORTABLE. Self-documenting code is good...
3. Because the relevant interface is in the declaration, it *should*
be easier for compilers to provide more direct and meaningful error
messages. I prefer "Error : templatized type T in max() must be of
type SORTABLE." over "Error : operator< is not defined for type
FLEEM". This may just be a personal style kind of thing.
I seem to remember that you can use the "like" keyword to introduce
covariance constraints, as well. For example, the previous template
could also be written as:
template <typename T1:SORTABLE, T2:like T1> T1 max(T1 a, T2 b)
{
return a<b ? b : a;
}
The primary addition here is the second parameterized/templatized
type, which is also constrained, but is constrained to be "like" the
first type (T1). This means that T2 can be the same as T1, or it can
be any type derived from T1 (I think -- sorry, my Eiffel is a little
rusty). This is not especially meaningful for max(), but it can be
very useful for properly expressing constraints on generic classes
that need to manipulate different types, but need those types to have
specific relationships to each other.
I gave the above template form because Eiffel uses the "like" keyword,
but it looks unnecessary (and is, in that context). After all, the
declaration could just be:
template <typename T1:SORTABLE, T2:T1> T1 max(T1 a, T2 b)
and it would mean exactly the same thing (T2 is of type T1 or is
derived from T1). The "like" keyword is generally used inside
templatized classes to add members that are constrained to be "like"
one of the templatized types.
I have wandered, and I need to go read OOSC2 again, but the central
point (for those of you with the patience to put up with me this far)
is that Constrained Genericity and Type Covariance are useful
constructs that do not exist in C++ (without some painful twisting
around) and that I would like to see added to D.
Thank you for your time and consideration,
Mac Reiter
Software Engineer
I was thinking of something else that looks a lot like what you are
saying, but concerns operator oveloading. I'm gonna start a new
thread about it as to not go too much off topic on yours, but what
you are saying sounds very good to me. Read the new thread:
Operator overloading: A way to make everybody happy?
I'm going to point people from there to here, because I think these
two subjects are related.
--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail
Jan 22 2002








"OddesE" <OddesE_XYZ hotmail.com>