Creating type erasure
Suppose I have a class Base and three derived classes, Derived1,
Derived2, and Derived3. Suppose I also have this thing:
class Result {
boost::shared_ptr<Base> ptr; // This will always be a Derived1 or
a
Derived2 pointer, never Derived3
public:
int getProperty();
};
The value returned from getProperty() can be determined at compile-time
(ie. all Derived1 return the same value and all Derived2 return the
same value) - the limitation of Result::ptr to Derived1 or Derived2
pointers is that this property is not well-defined for Derived3. The
question I have is in implementing getProperty().
Suppose I have this class:
template <class Derived>
class DerivedProperty;
template<>
class DerivedProperty<Derived1> : public boost::integral_constant<int, 1>
{};
template<>
class DerivedProperty<Derived2> : public boost::integral_constant<int, 2>
{};
(BTW, How do you ensure that DerivedProperty is never instantiated with
Derived3 due to its not-well-definedness, Base due to its
incompleteness, or any unrelated class due to its unrelatedness?)
As Result::ptr will always be a Derived1 or a Derived2 pointer,
getProperty() should return DerivedProperty<Derived1>::value or
DerivedProperty<Derived2>::value, where appropriate. Except that
Result doesn't have any information on which subclass the pointer
should be.
From reading about how you can do type erasure in C++, I think I should
do something like this:
class Result {
struct ResultBase {
virtual boost::shared_ptr<Base> getPtr() = 0; //
In case the ptr
from before is needed elsewhere
virtual int getProperty() = 0;
};
template <class Derived>
struct ResultModel : public ResultBase {
// Has a constructor that takes in the pointer, virtual
destructor, etc.
boost::shared_ptr<Derived> ptr;
boost::shared_ptr<Base> getPtr() { return ptr; }
int getProperty() { return DerivedProperty<Derived>::value;
}
};
public:
template <class Derived>
Result(const boost::shared_ptr<Derived>& ptr) : impl(new
ResultModel<Derived>(ptr));
int getProperty() { return impl.getProperty(); }
private:
boost::shared_ptr<ResultBase> impl;
};
I believe that should be the proper way to do what I have described,
which retains enough flexibility that I can, say, later define a
Derived4 with a well-defined DerivedProperty, and not have to modify
Result. Is this true, and what other things should I be aware of if it
is?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]