petomalina
petomalina

Reputation: 2150

Using derived class in Template and storing it into vector of base class

I am trying to create a type-map in C++ using std::map and Type class which stores the type. Then there is one base class Base and some Derived classes which i want to store.

template <typename T>
class Type {

public:
    Type() {}

    virtual ~Type() {}
    virtual T* allocate() const { return new T; }
    virtual T* cast(void *object) const { return static_cast<T*>(object); }
};

This works just fine:

map<int, Base*> typeMap;
typeMap[1] = new Derive();

But when trying to do something like this, I got error: a value of type "Type< Derive> *" cannot be assigned to an entity of type "Type< Base> *"

map<int, Type<Base>*> typeMap;
typeMap[1] = new Type<Derive>();

Is there any chance to store something like this? I don't want any library solutions (non-opensource)

Upvotes: 0

Views: 236

Answers (2)

Jarod42
Jarod42

Reputation: 218138

Similar to @pmr's answer but using std::tuple

#include <tuple>
#include <type_traits>

class Base{};
class Derived : public Base {};

template<std::size_t i>
struct my_map
{
private:
    using myTuple = std::tuple<Base, Derived>;
public:
    using type = typename std::tuple_element<i, myTuple>::type;
};

static_assert(std::is_same<Base, my_map<0>::type>::value, "bad type");
static_assert(std::is_same<Derived, my_map<1>::type>::value, "bad type");

Upvotes: 2

pmr
pmr

Reputation: 59841

Specialize a struct on an integer for each type you would like to map.

#include <cstddef> // size_t

struct Base {};
struct Derived : Base {};

template<std::size_t i>
struct my_map;

// specialize the map (maybe shorten with a macro)
template<>
struct my_map<0> {
  using type = Base;
};

template<>
struct my_map<1> {
  using type = Derived;
};

// easier to use, if you compiler supports it:
template<std::size_t i>
using my_map_t = typename my_map<i>::type;


int main()
{
  my_map<0>::type* b1 = new Base();
  my_map<0>::type* b2 = new Derived();
  my_map<1>::type* d1 = new Derived();
  // my_map<1>::type* d2 = new Base(); error wrong type

  // prettier
  my_map_t<0>* b3 = new Base();

  return 0;
}

Upvotes: 1

Related Questions