I have a polymorphic value type implemented like so:
class ShapeValue {
public:
template<class T>
ShapeValue(const T& value) {
obj = make_unique<holder<T>>(value);
}
// ... appropriate copy constructors and such
void draw() { obj->draw(); }
private:
struct base {
virtual ~base() {}
virtual void draw() = 0;
};
template<class T>
struct holder<T> : public base {
T value;
void draw() override { value.draw(); }
}
unique_ptr<base> obj;
};
If you aren't familiar with this sort of thing, here's a good talk.
Ok, that's great. But now what if I want to cast my underlying object to some other interface?
Here's my motivation. Previously, I had defined things the typical way, like so:
class Shape {
virtual void draw() = 0;
};
and then I would define other interfaces, like:
class HasColor {
virtual Color color() = 0;
virtual void setColor(Color) = 0;
};
so I could define a shape as follows:
class MyShape : public Shape, public HasColor {
void draw() override;
Color color() override;
void setColor(Color) override;
};
So if I have a bunch of selected shapes and I want to set their color, I could iterate over all shapes and dynamic_cast<HasColor*>
. This proves to be quite convenient (my actual app isn't a drawing app, by the way, but has analogous data).
Can I do this for my polymorphic value type, in a way that my ShapeValue
interface doesn't need to know about every Has
interface? I could do the following, which isn't actually so bad, but not ideal:
HasColor* ShapeValue::toHasColor() { return obj->toHasColor(); }