Search code examples
c++templatesstaticnon-staticclass-members

Non-Static member variables creation like static singleton creation in C++


First, I really like the pattern of lazy initialization of singletons. I use it in the following way to get different kind of data with varying value types (The example is simplified):

class A
{
    template<typename T>
    const T& getData() const
    {
        static T data;
        return data;
    }
}

I know that the data variable is not connected to any instances of the class and that it exists until the program ends.

But what I want now, is that each instance of the class A should hold the variables in a non-static way and still there should be the flexibility of calling .getData<bool>() or with any other data type, without the need to specify each possible data type in the class definition.

Is that possible? I have not come up with an idea to implement that.

I thought of something with a container like:

template<A*, typename T>
class DataContainer
{
    T data;
}

With that one can extend the code to:

class A
{
    template<typename T>
    const T& getData() const
    {
        static DataContainer<this, T> container;
        return container.data;
    }
}

But that does not compile.

Does anybody of you have an idea how to implement that?


Solution

  • Here's one idea, using Boost.any:

    #include <typeinfo>
    #include <type_index>
    #include <unordered_map>
    #include <boost/any.hpp>
    
    struct ThingGetter
    {
        template <typename T>
        T & get()
        {
            auto key = std::type_index(typeid(T));
            auto it = things.find(key);
    
            if (it == things.end())
            {
                it = things.emplace(key, boost::any(T())).first;
            }
    
            return boost::any_cast<T&>(*it);
        }
    
        std::unordered_map<std::type_index, boost::any> things;
    };
    

    This simple version assumes that each type can be value-initialized and creates a value-initialized value if no entry for the requested type exists. Alternative implementations could return a pointer that might be null and have a separate insertion interface.

    Usage:

    ThingGetter mythings;
    
    mythings.get<bool>() = true;
    mythings.get<double>() = 1.5;
    return mythings.get<int>();