.net - Managed class types as type of type parameter T (Error C2670) -
i want create generic function returning collection of type observablecollection<t>^
. callers pass managed class type type parameter t
. here 1 of tries of generic function, after explanations of other classes used:
generic<class t> t:canimal, gcnew() observablecollection<t>^ getitems(animaltype animaltype, int count) { observablecollection<t>^ animals = gcnew observablecollection<t>(); (int = 0; < count; i++) { if (animaltype == dog) { cdog^ dog = gcnew cdog(i, count - i); //canimal^ dog = gcnew cdog(i, count - i); //t dog = gcnew cdog(i, count - i); //t^ dog = gcnew cdog(i, count - i); animals->add(dog); } //else if (animaltype == cat) { ... } //... } return animals; }
because tried 1632 ways make function work can't tell why i've implemented :-/
class canimal
base class cdog
(assume there more animals, too). animaltype
enumeration intended used in function above determine correct class type instantiating , adding collection:
ref class canimal { public: canimal(){} canimal(int _age) { age = _age; } int age; }; ref class cdog : canimal { public: cdog(){} cdog(int _age, int _other) :canimal(age), other(_other) {} int other; }; enum animaltype { dog, cat, fish, // ... };
furthermore there's parent class holding observablecollection
's of dogs, cats, , on:
ref class czoo { private: observablecollection<cdog^>^ dogs; public: czoo() { dogs = getitems<cdog^>(animaltype::dog, 3); } };
the compiler throws following error:
error c2670: 'system::collections::objectmodel::collection::add' : function template cannot convert parameter 1 type 'cdog ^'
can tell me i'm doing wrong?
!!! solution !!!
based on david yaws' answer ended moving constructor parameters new function called initialize
, removed enum animaltypes
. final code changed following:
ref class canimal { internal: virtual void initialize(int _age, int _other) { age = _age; other = _other; } public: int age; int other; }; ref class cdog : canimal {}; ref class ccat : canimal {}; generic<class t> t:canimal, gcnew() observablecollection<t>^ getitems(int count) { observablecollection<t>^ animals = gcnew observablecollection<t>(); (int = 0; < count; i++) { t animal = gcnew t(); animal->initialize(i, count - i); animals->add(animal); } return animals; } ref class czoo { private: observablecollection<cdog^>^ dogs; observablecollection<ccat^>^ cats; public: czoo() { dogs = getitems<cdog^>(3); cats = getitems<ccat^>(7); } };
if remove stuff not relevant error, here's we've got:
generic<class t> t:canimal, gcnew() observablecollection<t>^ getitems() { observablecollection<t>^ animals = gcnew observablecollection<t>(); animals->add(gcnew cdog()); return animals; }
now, happens if invoked getitems<ccat^>()
? you're trying put cdog
list of ccat
, , won't work. that's error message saying: cdog
may not able converted t
.
if want this, there's couple possible solutions:
- you return list of
canimal
instead.cdog
valid put list ofcanimal
. - you change how initialize list of
t
.
i'd recommend latter, , this:
generic<class t> t:canimal, gcnew() observablecollection<t>^ getitems(int count) { observablecollection<t>^ animals = gcnew observablecollection<t>(); (int = 0; < count; i++) { t animal = gcnew t(); animal->initialize(i, count-i); animals->add(animal); } return animals; }
- because you've got
gcnew()
constraint, means class has zero-parameter constructor, , you're allowed call using typet
. - move constructor parameters have method defined on
canimal
. way can call ont
. - i removed enum parameter. don't need it; you're specifying animal want via generic.
- i recommend change regardless of how implement this. otherwise, you'll have consider things
getitems<cdog^>(animaltype::cat, 3)
should do.
- i recommend change regardless of how implement this. otherwise, you'll have consider things
Comments
Post a Comment