C++ minimal std::any

A few days ago I wrote a simple alternative to std::any. It is heavily inspired by Sean Parent’s talk Better Code: Runtime Polymorphism.

If you don’t know what std::any is, basically it is a structure that can hold data of any type, while maintaining the value semantics.

With C++11 this is really easily done in just a few lines. I’m still unsure how and where can I use it.

// "struct object" is the magic type.
// Basically "object" holds a pointer to "object_storage_interface".
//
// This "object_storage_interface" basically holds the *actual data* 
// and provides a few methods used for communication 
// between the data and the "srtuct object".

#include <iostream>
#include <memory>
#include <string>
#include <vector>

struct object_storage_interface
{
    object_storage_interface() {}
    
    virtual ~object_storage_interface() = default;
    virtual std::unique_ptr<object_storage_interface> createACopy() const = 0;
};

template<typename T>
struct Tobject_storage : public object_storage_interface
{
    Tobject_storage() = default;
    Tobject_storage(T v) :
        m_value(std::move(v))
    {}

    std::unique_ptr<object_storage_interface> createACopy() const override
    {
        return std::make_unique<Tobject_storage>(m_value);
    }

    T m_value;
};

struct object
{
    object() = default;

    template <typename T>
    object(const T& ref) :
        m_storage(std::make_unique<Tobject_storage<T>>(std::move(ref)))
    { }

    object(const object& ref) :
        m_storage(ref.m_storage ? ref.m_storage->createACopy() : nullptr)
    {}

    object(object&&) noexcept = default; // noexcept ...

    object& operator=(const object& ref)
    {
        m_storage = ref.m_storage ? ref.m_storage->createACopy() : nullptr;
        return *this;
    }

private :

    std::unique_ptr<object_storage_interface> m_storage;
};

int main()
{
    std::vector<object> objects;

    object a = 5;
    object b = std::string("123");

    object x = b;
    x = a;

    objects.emplace_back(a);
    objects.emplace_back(b);
    objects.emplace_back(x);

    return 0;
}
comments powered by Disqus