Question

I've been learning C++, coming from C#, where I've gotten used to using service providers: basically a Dictionary<Type, object>. Unfortunately, I can't figure out how to do this in C++. So the questions are basically:

  1. How would I make a dictionary in C++.

  2. How would I use 'Type' with it, as far as I know there is no 'Type' in C++.

  3. Same as above, but with 'object'.

Thanks!

Was it helpful?

Solution

I'm assuming that you're trying to map a type to a single object instance. You could try something along these lines:

#include <typeinfo>
#include <map>
#include <string>
using namespace std;

class SomeClass
{
public:
    virtual ~SomeClass() {} // virtual function to get a v-table
};

struct type_info_less
{
    bool operator() (const std::type_info* lhs, const std::type_info* rhs) const
    {
        return lhs->before(*rhs) != 0;
    }
};

class TypeMap
{
    typedef map <type_info *, void *, type_info_less> TypenameToObject;
    TypenameToObject ObjectMap;

public:
    template <typename T> 
    T *Get () const
    {
        TypenameToObject::const_iterator iType = ObjectMap.find(&typeid(T));
        if (iType == ObjectMap.end())
            return NULL;
        return reinterpret_cast<T *>(iType->second);
    }
    template <typename T> 
    void Set(T *value) 
    {
        ObjectMap[&typeid(T)] = reinterpret_cast<void *>(value);
    }
};

int main()
{
    TypeMap Services;
    Services.Set<SomeClass>(new SomeClass());
    SomeClass *x = Services.Get<SomeClass>();
}

In C++ types are not first-class objects in their own right, but at least the type-name is going to be unique, so you can key by that.

Edit: The names aren't actually guaranteed to be unique, so hold on to the type_info pointers and use the before method to compare them.

OTHER TIPS

You probably want to look at the STL map template. C++ certainly does have types (hard to have inheritance without it), just no specific defined "Type" class.

The STL has two associative containers: std::map<K,V> andstd::multimap. There is also std::set<V> which should be an adaptor of std::map<V,void>, but as such it isn't an associative container. The multimap is similar to the map, only it allows multiple identical keys within the same container. Both map and multimap hold elements of type std::pair<K,V>. In other words, std::map<K,V>::value_type == std::pair<K,V>, but std::map<K,V>::key_type == K and std::map<K,V>::mapped_type == V.

As for "Type", I am not entirely sure what you mean. If you mean parameterized classes then C++ calls this "Template Programming", or "Generic Programming". In the above, std::map<K,V> is parameterized over K and V for the keys' type and the values' type. C++ also supports template functions:

template<typename T>
void f(T o);

will declare a function that takes as a parameter any type at all, including primitive types. C++ doesn't support generic type resolution, such that the type T must of certain hierarchy. For now, all you can do is just assume the passed type is indeed of the correct hierarchy, and the compiler will complain if you try to call a non-declared function over an object of that type.

template<typename T>
void f(T o) {
    o.do_it();
}

The above will work as long as T defines the method do_it().

A dictionary sounds like an STL map to me: std::map<K, T>. Have a look at the Standard Template Library - it's brilliant. It's been part of ANSI C++ for a while. Microsoft has a nice implementation from PJ Plauger, if I recall correctly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top