/*
    This is an evolved solution based on an SO answer found
    at http://stackoverflow.com/a/17159495/845568
  
    1. I changed the name from `Data` to `Value` as it seems more logical in
       this case.
    2. It uses the same PIMPL approach as the original.
    3. It uses `std::unqiue_ptr` instead of `new` and `delete` to manage object
       lifetime
    4. It uses an interface approach for the base class of the value container.
       An implementation in the base class is unnecessary.
    5. It uses a template class for the value container and includes a
       specialization for `void`. This allows for a default constructor in `Value`.
*/
#include <iostream>
#include <memory>

// Interface for value objects
struct ValueImpl
{
    virtual ~ValueImpl() {};
    virtual std::unique_ptr<ValueImpl> clone() const = 0;
    virtual void increments() = 0;
    virtual void print() const = 0;
};

// Templated implementation of value class for easier use
template<typename T>
class ValueT : public ValueImpl
{
public:

    ValueT(const T &k) : value_(k) {}

    virtual std::unique_ptr<ValueImpl> clone() const
    {
        return std::unique_ptr<ValueImpl>(new ValueT(value_));
    }

    void increments()
    {
        value_++;
    }

    void print() const
    {
        std::cout << typeid(T).name() << "(" << value_ << ") " << std::endl;
    }

private:

    T   value_;
};

// Specialization of value class to provide a default ctor in Value
template<>
class ValueT<void> : public ValueImpl
{
public:

    ValueT() {}

    virtual std::unique_ptr<ValueImpl> clone() const
    {
        return std::unique_ptr<ValueImpl>(new ValueT());
    }

    void increments() { }

    void print() const
    {
        std::cout << "(void)" << std::endl;
    }
};


// Value container using PIMPL idiom.
class Value
{
public:

    Value() : value_(new ValueT<void>) {}
    Value(const Value & other) : value_(other.value_->clone()) {}

    // Construct a Value given an actual implementation:
    // This allocates memory on the heap, hidden in clone()
    explicit Value(const ValueImpl& value) : value_(value.clone()) {}

    // Destruct the data: must deallocate the memory
    virtual ~Value() {}

    // Copy constructor and assignment operator:
    // Implements a value semantics by allocating new memory 
    Value & operator=(const Value & other) 
    {
        if(&other != this)
        {
            value_ = std::move(other.value_->clone());
        }
        return *this;
    }

    // Custom "polymorphic" methods
    void increments() { value_->increments(); }
    void print()      { value_->print(); }

private:

    std::unique_ptr<ValueImpl>  value_;
};



int main()
{
    // use typedefs if you like. they are really not necessary for this example
    Value iv(ValueT<int>(1));
    Value dv(ValueT<double>(1.2));

    Value value;

    value.print();
    value = dv;
    value.print();
    value = iv;
    value.print();
    value.increments();
    value.print();
}
