Specialization with generics

  • Thread starter Thread starter Michael Sparks
  • Start date Start date
M

Michael Sparks

I started writing some code with the 2.0 beta compiler, and found out
quickly that specialization is not supported with generics.

For example, I want to do something like this:

class number ...
class integer : number ...
class real : number ...
class multiplier<_number> where _number : number ...
class multiplier<_number> where _number : integer ...

Here, the first implementation of 'multiplier' will work with 'number'
or anything that derives from 'number'. The second implementation of
'multiplier' will work with 'integer' or anything that derives from
'integer. Since 'integer' derives from 'number', it is a
specialization. At least that's what I'm calling it - there may be a
more appropriate name in this exact context.

This may be preaching to the choir - I haven't been in this newsgroup
for a while, but here is an example of where it would be useful to have
the above feature:

class fancy_computation<_number> where _number : number
{
public _number doit(_number x,_number y)
{
multiplier<_number> mult=new multiplier<_number>;
return mult.doit(x,y);
}
}

The advantage here is that I can type 'fancy_computation<integer>' and
the compiler will automatically select the correct implementation of
'multiplier'.

Anyway, it look like this is not supported. I am wondering what
specific limitation caused the design team to leave out support for
specialization.

Thanks for any insight you can provide.

Mike
 
No, user-defined specialization is not supported by generics. Apparrently
the designers felt that user-defined specialization was too tied to C++.
Since most other differences between templates and generics are emergent
from the different instantiation times (compile-time for templates, run-time
for generics) I wouldn't be too surprised if this had an impact on
user-defined specialization as well.
 
Michael said:
The advantage here is that I can type 'fancy_computation<integer>' and
the compiler will automatically select the correct implementation of
'multiplier'.

you can do something like that with runtime-dispatch using if ( x
instanceof ) ..., that won't give you qualified-type (static) dispatch
though -- but that probably isn't what you want anyway.
Anyway, it look like this is not supported. I am wondering what
specific limitation caused the design team to leave out support for
specialization.

I can think of at least one thing that's always been a c++ problem:
specialization allows distribution of the definition of the specialized
set of classes, giving different semantics to statements depending on
how much of the specialization you've seen.

In C# you don't include files (headers) but access types in libraries,
so the good old "specialization in separate header-file changes
behaviour of program" cannot happen, but specialization in separate
type-libraries .... the horror!

X.lib
class foo<_number>: where _number: number { static number doit(number,
number); }

Y.lib
class foo<_number>: where _number: int { static int doit(int, int); }
 
Anyway, it look like this is not supported. I am wondering what
I can think of at least one thing that's always been a c++ problem:
specialization allows distribution of the definition of the specialized
set of classes, giving different semantics to statements depending on
how much of the specialization you've seen.

That possibility occurred to me, but then I remembered partial classes,
which are also new with this beta. That allows you do define different
parts of the same class in multiple files, and the compiler magically
figures out how to piece them together. The same could be done here,
but instead of piecing together a single class, you are piecing together
the collection of specializations for a class.

It is limited in that a user of your library couldn't create his own
specialization, but that could probably lead to security trouble anyway,
so it would be an acceptable loss (to me at least).

Mike
 
Michael Sparks wrote:

Can't you make it work with a simple switch (if...else...) on the types?
If not, then the (hack :) visitor-pattern can help you.
That possibility occurred to me, but then I remembered partial classes,
which are also new with this beta. That allows you do define different
parts of the same class in multiple files, and the compiler magically
figures out how to piece them together. The same could be done here,
but instead of piecing together a single class, you are piecing together
the collection of specializations for a class.

Are you allowed to specify different parts of the same class in separate
type-libraries? That would surprise me, but then again, I have
absolutely zero .NET2.0 experience.
It is limited in that a user of your library couldn't create his own
specialization, but that could probably lead to security trouble anyway,
so it would be an acceptable loss (to me at least).

You are proposing a limitation: that all specializations must be in the
same type-library, right?

Well that may work..., but it would take quite a bit of usability out of
it, especially since all the types specialized for would have to be
known inside that type-library.

Restrictions like "but it would work just fine for my exact case" tends
to suggest that it should not be a language feature.

BTW: in your case, wouldn't you *really* rather want dynamic-type
dispatch? so the "right" operation gets invoked even if an integer
argument is only qualified (static-typed) as number?

Don't get me wrong, I can see how it is handy (having done a fair amount
of c++), but it also brings its own problems, you are putting semantics
of the code into the type and dispatch based on that, effectively
creating a "meta-language" using the dispatch mechanism.

Before you known it you will be wishing for the complexity of the C++
template-resolution (are/have you by any chance (been) a c++ programmer?).

I think this comes down to "meta-programming", making a program that wil
make the program you want, in contrast to expressing the program directly.

C# is (virtually) impossible to "meta-program" in (you only have
compile-time dispatch by overloading), so you probably shouldn't try to
do it.

In C++, you can do meta-programming (using templates, mainly because of
typedefs and specialization), but it sucks, boost helps - but it is
still VERY complicated and if there is a reasonable other choice, I
don't do it.

In scheme, meta-prgramming is a breeze, with the "`" quasiquote
operator, and in scheme you find yourself meta-program when appropriate.
 
Back
Top