This project is read-only.
Generics

Generics are much more complicated than what they seem. They are not Java syntactic sugar, .NET JIT actually understands generics and do great things with it.
CrossNet uses C++ templates to emulate generics. There are some limitations though, but in most cases you probably won't notice them.
Fortunately C++ templates are more lenient that .NET generics, so constraints are actually not needed (but we could actually use them to do some optimizations).

First let's talk about what is not supported by CrossNet:

class TestGenericVirtual
{
    public virtual T Foo<T>(T a)
    {
        return (a);
    }
}


The reason is that in C++, virtual functions can't be templated.

And by extension, this is not supported:

interface ITestGenericMethod
{
    string Foo<V>(string a, V b);
}


Interfaces are emulated with abstract classes, all the methods in the interface are also abstract. The interface itself can be generic.

So this is perfectly supported:

interface ITestSimpleGenericInterface<U>
{
    U Foo(U a);
}




The two other unsupported cases are:
  • Generic types dynamically created (doesn't fit well with statically compiled templates ;).
  • Static members for generic types (Will be supported with next change set around end of September).

Also note that .NET supports overloading of name for generics, the number of generic arguments differentiates the class / method (there is no default parameter in .NET).

Example of C# code:

public class Foo
{
    public void Bar()
    {
    }
    public void Bar<X>()
    {
    }
    public void Bar<X, Y>()
    {
    }
    public void Bar<X, Y, Z>()
    {
    }
}


Generated C++ code:

class TestGenericCollision__Foo : public ::System::Object
{
    ...
    public:
    ::System::Void Bar();
    public:
    template <typename X>
    ::System::Void Bar__G1();
    public:
    template <typename X, typename Y>
    ::System::Void Bar__G2();
    public:
    template <typename X, typename Y, typename Z>
    ::System::Void Bar__G3();
    ...
};


As you can see G? (where ? represents the number of generic arguments) is appended to differentiate the generic from the non-generic function.
You can have some very complicated syntax but CrossNet is hiding everything for you.

CrossNet manages creation of System.Type, interface map, interface ID dynamically for generic types.

C# Code:

static public void gmeth1<T>()
{
    Console.WriteLine(typeof(Set<T>));
    Console.WriteLine(typeof(Map<T, T>));
    Console.WriteLine(typeof(T));
    gmeth2<T, Set<T>>();
    gmeth2<Set<T>, T>();
}


Generated C++ code:

template <typename T>
::System::Void CrossNetUnitTest::Generic::TestRegressionGenmeth4__M::gmeth1__G1()
{
    ::System::Console::WriteLine(CN_TYPEOF(::CrossNetUnitTest::Generic::TestRegressionGenmeth4__Set__G1<T>));
    ::System::Console::WriteLine(CN_TYPEOF(::CrossNetUnitTest::Generic::TestRegressionGenmeth4__Map__G2<__W2__(T, T)>));
    ::System::Console::WriteLine(CN_TYPEOF(T));
    ::CrossNetUnitTest::Generic::TestRegressionGenmeth4__M::gmeth2__G2<__W2__(T, ::CrossNetUnitTest::Generic::TestRegressionGenmeth4__Set__G1<T> *)>();
    ::CrossNetUnitTest::Generic::TestRegressionGenmeth4__M::gmeth2__G2<__W2__(::CrossNetUnitTest::Generic::TestRegressionGenmeth4__Set__G1<T> *, T)>();
}


Note the macro CN_TYPEOF to get the corresponding System::Type object from the C++ type.
The macro W? is just a wrapper around the template parameters. We are using the wrapper macro because C++ macros don't recognize < > to describe template parameters as partitioner.

So this would not compile:

    ::System::Console::WriteLine(CN_TYPEOF(::CrossNetUnitTest::Generic::TestRegressionGenmeth4__Map__G2<T, T>));


Because the preprocessor would undertand it as 2 parameters for the macro CN_TYPEOF that can receive only one parameter.
I guess we could use variadic macros to get around that but not all C++ compiler does support it.

Finally there are much more tricks to make the generics work, but I will describe them later...

Last edited Sep 24, 2007 at 5:56 AM by OlivierNallet, version 4

Comments

No comments yet.