OneOfAType container -- storing one each of a given type in a container -- am I off base here?
<p>I've got an interesting problem that's cropped up in a sort of pass based compiler of mine. Each pass knows nothing of other passes, and a common object is passed down the chain as it goes, following the chain of command pattern.</p>

<p>The object that is being passed along is a reference to a file.</p>

<p>Now, during one of the stages, one might wish to associate a large chunk of data, such as that file's SHA512 hash, which requires a reasonable amount of time to compute. However, since that chunk of data is only used in that specific case, I don't want all file references to need to reserve space for that SHA512. However, I also don't want other passes to have to recalculate the SHA512 hash over and over again. For example, someone might only accept files which match a given list of SHA512s, but they don't want that value printed when the file reference gets to the end of the chain, or perhaps they want both, or... .etc.</p>

<p>What I need is some sort of container which contain only one of a given type. If the container does not contain that type, it needs to create an instance of that type and store it somehow. It's basically a dictionary with the type being the thing used to look things up.</p>

<p>Here's what I've gotten so far, the relevant bit being the <code>FileData::Get&lt;t&gt;</code> method:</p>

<pre><code>class FileData;
// Cache entry interface
struct FileDataCacheEntry
{
    virtual void Initalize(FileData&amp;)
    {
    }
    virtual ~FileDataCacheEntry()
    {
    }
};

// Cache itself
class FileData
{
    struct Entry
    {
        std::size_t identifier;
        FileDataCacheEntry * data;
        Entry(FileDataCacheEntry *dataToStore, std::size_t id)
            : data(dataToStore), identifier(id)
        {
        }
        std::size_t GetIdentifier() const
        {
            return identifier;
        }
        void DeleteData()
        {
            delete data;
        }
    };
    WindowsApi::ReferenceCounter refCount;
    std::wstring fileName_;
    std::vector&lt;Entry&gt; cache;
public:
    FileData(const std::wstring&amp; fileName) : fileName_(fileName)
    {
    }
    ~FileData()
    {
        if (refCount.IsLastObject())
            for_each(cache.begin(), cache.end(), std::mem_fun_ref(&amp;Entry::DeleteData));
    }
    const std::wstring&amp; GetFileName() const
    {
        return fileName_;
    }

    //RELEVANT METHOD HERE
    template&lt;typename T&gt;
    T&amp; Get()
    {
        std::vector&lt;Entry&gt;::iterator foundItem = 
            std::find_if(cache.begin(), cache.end(), boost::bind(
            std::equal_to&lt;std::size_t&gt;(), boost::bind(&amp;Entry::GetIdentifier, _1), T::TypeId));
        if (foundItem == cache.end())
        {
            std::auto_ptr&lt;T&gt; newCacheEntry(new T);
            Entry toInsert(newCacheEntry.get(), T::TypeId);
            cache.push_back(toInsert);
            newCacheEntry.release();
            T&amp; result = *static_cast&lt;T*&gt;(cache.back().data);
            result.Initalize(*this);
            return result;
        }
        else
        {
            return *static_cast&lt;T*&gt;(foundItem-&gt;data);
        }
    }
};

// Example item you'd put in cache
class FileBasicData : public FileDataCacheEntry
{
    DWORD    dwFileAttributes;
    FILETIME ftCreationTime;
    FILETIME ftLastAccessTime;
    FILETIME ftLastWriteTime;
    unsigned __int64 size;
public:
    enum
    {
        TypeId = 42
    }
    virtual void Initialize(FileData&amp; input)
    {
        // Get file attributes and friends...
    }
    DWORD GetAttributes() const;
    bool IsArchive() const;
    bool IsCompressed() const;
    bool IsDevice() const;
    // More methods here
};

int main()
{
    // Example use
    FileData fd;
    FileBasicData&amp; data = fd.Get&lt;FileBasicData&gt;();
    // etc
}
</code></pre>

<p>For some reason though, this design feels wrong to me, namely because it's doing a whole bunch of things with untyped pointers. Am I severely off base here? Are there preexisting libraries (boost or otherwise) which would make this clearer/easier to understand?</p>
