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:
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 Testwhich should allow us to
gcnewgeneric type parameters.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?
You could ask about this on Andy Rich’s blog.
I must have messed up the anchor tag, here’s the URL:
http://blogs.msdn.com/arich/
Mike, you typed hrer instead of href π
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.
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’.
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?
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 π
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?