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 to 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 and outputs right size of vector, but if case line in switch statement (inside Storage.h) is uncommented, compiler(g++) throws
“error: cannot convert ‘std::vector < Potato*>* ‘ to ‘std::vector< Apple*>* ‘ in assignment”.
It is like compiler trying out both cases anyway, and i cant find is it possible and how to avoid this.
I need help with this and maybe some advice on a whole thing(one interface for containers of different types), I’ve started learning C++ recently and probably the way i try this to do here is a total mess.
Your code doesn’t compile because both
caseshould compile which is not possible, as the type differs in bothcase.One solution to this problem is to use overload instead of function template as (which means, there is NO need of
typeIDin your class!) :And call it as:
The trick here is that you have two overloads, each takes one argument of different type, and so you use
static_cast<FoodType*>(0)to help the compiler to pick the correct overload based on the type of the expressionstatic_cast<FoodType*>(0)which would be either of typeApple*orPotato*.@Gorpik said in the comment that both (this as well as other solution) are ugly, so here is another attempt to solve this problem.
Define a
base_storageclass template as:This base class stores food items of one type only, but in the question, we need to store food items of two types. So in order to do that, lets define another class
Storagederiving from the above class template as:Note two points here:
storagedoesn’t have any member data now. It just forward the call to the base class which is chosen based on the type of template argumentFoodType.is-arelationship.See the online demo of this solution here : http://ideone.com/Ykjo5
The beauty of this solution is that if you want to make it work for three types of food, then all you need to derive it from three base classes as:
Demo : http://ideone.com/lnMds