Instantiating a generic type parameter in C++/CLI

I was working on some code and encountered an annoying problem with generics in C++/CLI. See the following code :-

generic<typename T> where T:Base ref class Test
{
public:
    Test()
    {
        T t = gcnew T(); // won't compile
        t->Hello();
    }
};

It won’t compile 😦

You get this error message :-

C3227: 'T' : cannot use 'gcnew' to allocate a generic type

Crap! That’s what I say! You can’t do much with generics if you cannot instantiate a generic type parameter. Luckily there is a work around (Thanks to Ben Schwehn) :-

generic<typename T> where T:Base ref class Test
{
public:
    Test()
    {
        T t = Activator::CreateInstance<T>();
        t->Hello();
    }
};

You just use the generic overload of Activator::CreateInstance. Cool huh? :nerd:

Advertisements

10 thoughts on “Instantiating a generic type parameter in C++/CLI

  1. BTW I believe a future compiler update will add syntactic features that will allow us to do something like :-

    generic<typename T> where T:Base, gcnew() ref class Test

    which should allow us to gcnew generic type parameters.

  2. Thanks for mentioning me 🙂

    I hope there will be a compiler update, as it is you can’t dispose/delete an generic type paramter:

    delete results in “error C2541: ‘delete’ : cannot delete objects that are not pointers” and Dispose in “error C2039: ‘Dispose’ : is not a member of ‘System::IDisposable’” (hehe)
    or is there a workaround as well?

  3. Hey Ben,

    I used this for deleting it :-

    T t = Activator::CreateInstance<T>();
    t->Hello();
    delete safe_cast<Object^>(t);

    And the correct destructor method (Dispose) got invoked. Not sure of it has any hidden issues though. Maybe I should ask this in the NG.

  4. Nish,
    that’s a clever trick!
    If you want runtime checking whether T actually implements IDisposable you can cast to IDisposable instead. (delete checks whether IDisposable is implemented and just does nothing if it isn’t). I believe this is as close as you can get to the ‘real thing’.

  5. I’ve just noticed (and posted to the NG) that the generated IL contains a

    box !T

    operation, ie the generic parameter is boxed even though it isn’t a valuetype. Could this cause problems?

  6. Well, Brandon says that in Whidbey, it’s legal to box ref objects (it’s required to handle generics). Nothing happens if you try to box a ref object, so it’s safe I guess 🙂

  7. I tried this:

    T t = System::Activator::CreateInstance( sourceT );
    and get the following error:
    Error 4 error C2780: ‘T System::Activator::CreateInstance(void)’ : expects 0 arguments – 1 provided.

    Any ideas how to rectify this?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s