I would like a class Value, which both has a run-time polymorphic behaviour, and a value semantics. For instance, I would like to be able to do things like:
// create polymorphic data
Value v1 = IntValue(42);
Value v2 = DoubleValue(12.3);
// copy-by-value semantics
Value v3 = v1;
v3.increments();
Value v4;
v4 = v2;
v4.increments();
// possibly put them in my favourite container
MyList<Value> l;
l << v1 << v2 << v3 << v4;
// print them: "Int(42) Double(12.0) Int(43) Double(13.0) "
for(int i=0; i<l.size(); i++) l[i].print();
Is it possible, and if yes, how?
Note: Using boost or C++11 smart pointers as here is not desired: they make the caller code verbose, use -> instead of ., and do not have copy constructors or assignment operators implementing a true value semantics. Also, this question doesn't target specifically containers.
polymorphic_value has been proposed for standardisation and has some of the semantics you require. You'll have to define your own operator << though.
A polymorphic_value<T> may hold a an object of a class publicly derived from T, and copying the polymorphic_value will copy the object of the derived type.
polymorphic_value<T> is implemented with type erasure and uses the compiler-generated copy-constructor of the derived objects to correctly copy objects stored as polymorphic_value<BaseType>.
Copy constructors and assignment operators are defined so that the objects are value-like. There is no need to use or define a custom clone method.
In brief:
template <class T>
struct control_block
{
virtual ~control_block() = default;
virtual T* ptr() = 0;
virtual std::unique_ptr<control_block> clone() const = 0;
};
template <class T>
class polymorphic_value {
std::unique_ptr<control_block<T>> cb_;
T* ptr_ = nullptr;
public:
polymorphic_value() = default;
polymorphic_value(const polymorphic_value& p) :
cb_(p.cb_->clone())
{
ptr_ = cb_->ptr();
}
T* operator->() { return ptr_; }
const T* operator->() const { return ptr_; }
T& operator*() { return *ptr_; }
const T& operator*() const { return *ptr_; }
// Some methods omitted/deferred.
};
Specializations of the control block allow other constructors to be defined.
Motivation and design is discussed here :
https://github.com/jbcoe/polymorphic_value/blob/master/talks/2017_1_25_cxx_london.md
and here
https://github.com/jbcoe/polymorphic_value/blob/master/draft.md
A full implementation with tests can be found here:
https://github.com/jbcoe/polymorphic_value
It's hard to know what you're trying to achieve here, but at first guess it seems that the (upcoming) Boost Type Erasure library might be suitable?
any<
mpl::vector<
copy_constructible<>,
typeid_<>,
incrementable<>,
ostreamable<>
>
> x(10);
++x;
std::cout << x << std::endl; // prints 11
(Example from docs).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With