.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
canimalinstead.cdogvalid 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