lundi 4 septembre 2017

Type erasure: Retrieving value - type check at compile time

I have a limited set of very different types, from which I want to store instances in a single collection, specifically a map. To this end, I use the type erasure idiom, ie. I have a non-templated base class from which the templated, type specific class inherits:

struct concept
{
   virtual std::unique_ptr<concept> copy() = 0; // example member function
};

template <typename T>
struct model : concept
{
   T value;
   std::unique_ptr<concept> copy() override { ... }
}

I then store unique_ptrs to concept in my map. To retrieve the value, I have a templated function which does a dynamic cast to the specified type.

template <typename T>
void get(concept& c, T& out) {
   auto model = dynamic_cast<model<T>>(&c);
   if (model == nullptr) throw "error, wrong type";
   out = model->value;
}

What I don't like about this solution is, that specifying a wrong T is only detected at runtime. I'd really really like this to be done at compile time.

My options are as I see the following, but I don't think they can help here:

  • Using ad hoc polymorphism by specifying free functions with each type as an overload, or a template function, but I do not know where to store the result.

    • Using CRTP won't work, because then the base class would need to be templated.

    • Conceptually I would need a virtual function which takes an instance of a class where the result will be stored. However since my types are fundamentally different, this class would need to be templated, which does not work with virtual.

Anyways, I'm not even sure if this is logically possible, but I would be very glad if there was a way to do this.

Aucun commentaire:

Enregistrer un commentaire