c++ - Different types assignment in switch state cases, inside template function -
apple.h
class apple { public: apple(int); static int typeid; private: int id_; };
apple.cpp
#include "apple.h" apple::apple(int pid) { id_ = pid; }
potato.h, potato.cpp identical apple
storage.h
#pragma once #include "apple.h" #include "potato.h" #include <vector> class storage { public: storage(); template<typename foodname> void store(foodname * object){ (*getbasket<foodname>()).push_back(object); }; template<typename foodname> int countsize(){ return (*getbasket<foodname>()).size(); }; private: std::vector<apple*> applebasket_; std::vector<potato*> potatobasket_; template <typename foodname> std::vector<foodname*> * getbasket(){ std::vector<foodname*> * result; switch(foodname::typeid){ case 0: result = &applebasket_; break; case 1: //result = &potatobasket_; break; } return result; } };
storage.cpp
#include "storage.h" int apple::typeid; int potato::typeid; storage::storage() { apple::typeid = 0; potato::typeid =1; }
main.cpp
#include "storage.h" #include <iostream> int main() { apple* apple; potato* potato; storage storage; int i; for(i = 0;i < 7;i++){ apple = new apple(i); storage.store<apple>(apple); } std::cout<<storage.countsize<apple>(); return 0; }
this code works , outputs right size of vector, if case line in switch statement (inside storage.h) uncommented, compiler(g++) throws "error: cannot convert ‘std::vector < potato*>* ' 'std::vector< apple*>* ' in assignment". compiler trying out both cases anyway, , cant find possible , how avoid this. need , maybe advice on whole thing(one interface containers of different types), i've started learning c++ , way try here total mess.
your code doesn't compile because both case
should compile not possible, type differs in both case
.
one solution problem use overload instead of function template (which means, there no need of typeid
in class!) :
std::vector<apple*> * get_basket(apple *) { return &applebasket_; //return pointer apple basket } std::vector<potato*> * get_basket(potato *) { return &potatobasket_; //return pointer potate basket }
and call as:
template<typename foodtype> void store(foodtype * object) { std::vector<foodtype> * basket = get_basket(static_cast<foodtype*>(0)); basket->push_back(object); }
the trick here have 2 overloads, each takes 1 argument of different type, , use static_cast<foodtype*>(0)
compiler pick correct overload based on type of expression static_cast<foodtype*>(0)
either of type apple*
or potato*
.
@gorpik said in comment both (this other solution) ugly, here attempt solve problem.
define base_storage
class template as:
template<typename foodtype> class base_storage { std::vector<foodtype*> m_storage; public: void store(foodtype *fooditem) { m_storage.push_back(fooditem); } size_t count() const { return m_storage.size(); } };
this base class stores food items of one type only, in question, need store food items of two types. in order that, lets define class storage
deriving above class template as:
class storage : private base_storage<apple>, private base_storage<potato> { public: template<typename foodtype> void store(foodtype * fooditem) { base_storage<foodtype>::store(fooditem); } template<typename foodtype> size_t count() const { return base_storage<foodtype>::count(); } };
note 2 points here:
- the class
storage
doesn't have member data now. forward call base class chosen based on type of template argumentfoodtype
. - it derives privately base classes. not
is-a
relationship.
see online demo of solution here : http://ideone.com/ykjo5
the beauty of solution if want make work three types of food, need derive three base classes as:
class storage : private base_storage<apple>, private base_storage<potato>, private base_storage<mango> //added line! { //same before; no change @ ! };
demo : http://ideone.com/lnmds
Comments
Post a Comment