Assignment of various types in cases of switch states, inside the 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 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 prints the right size of the vector, but if the case line in the switch statement (inside Storage.h) is uncommented, the compiler (g ++) throws "error: cannot convert 'std :: vector <Potato *> *' to 'std :: vector <Apple *> * 'on assignment. " It looks like the compiler checks both cases anyway, and I cannot find it, and how to avoid it. I need help with this and maybe some advice on the whole subject (one interface for containers of different types), I started learning C ++ recently, and probably the way I'm trying to do this is a complete mess.

+5
4

, case , , case.

( , typeID!):

std::vector<Apple*> * get_basket(Apple *)
{
   return &applebasket_;  //return pointer to the apple basket
}

std::vector<Potato*> * get_basket(Potato *)
{
   return &potatobasket_; //return pointer to the potate basket
}

:

template<typename FoodType> 
void store(FoodType * object)
{
    std::vector<FoodType> * basket = get_basket(static_cast<FoodType*>(0));
    basket->push_back(object);
}

, , , static_cast<FoodType*>(0), static_cast<FoodType*>(0), Apple*, Potato*.


@Gorpik , (, ) , .

base_storage :

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();
        }
};

, . , , Storage, , :

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();
        }
};

:

  • Storage -. , FoodType.
  • . , is-a.

- : http://ideone.com/Ykjo5

, , , , , :

class storage : private base_storage<Apple>, 
                private base_storage<Potato>,
                private base_storage<Mango>   //added line!
{

     //same as before; no change at all !

};

: http://ideone.com/lnMds

+2

typeID. .

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();
};


template <> std::vector<Apple*> * Storage::getBasket()
{
    return &applebasket_;
} 
template <> std::vector<Potato*> * Storage::getBasket()
{
    return &potatobasket_;
} 
+2

std::vector<Apple *> std::vector<Potato *> - . ++ , .

Apple Potato , Food, std::vector<Food *>, std::vector<Apple *>, std::vector<Food *>.

getBasket() , , , switch . , foodStuff, , , switch. , , , return, , , .

So, you need to either store and retrieve Appleit Potatoseparately (perhaps using templates, as some of the other answers suggested), or use inheritance so that you can store them in what the common parent type understands.

+2
source

Specialize getBasketfor two cases.

Or, better, don't mix abstraction levels this way and just provide separate containers for potatoes and apples.

0
source

All Articles