How to share different objects between some classes
What is the best way to share different objects between some classes in a general way?
For example, class A can store an object o with a string as a key in a register, and class B can access it using the key.
My first idea was to create a register (singleton) that has a hash table as a member, using a string as key and a void pointer as value. But there must be a better solution for this?
source to share
From your clarification:
template <typename OB>
class A {
std::unordered_map<std::string, OB> hash;
public:
OB const& get(std::string const&) const;
void add(OB const& object, std::string const&);
};
That is A<int>
, it is a class that stores int
objects by name, and it A<std::set<float>>
is a class that stores sets of floats by name. You cannot mix them. This is in line with the basic C ++ philosophy: the type theA.get("foo")
is determined at compile time, not by what you insert at runtime.
In C ++, you can "mix" multiple derived types if you need it for your particular case. This is a little more complicated:
template <typename Base>
class A {
std::unordered_map<std::string, std::unique_ptr<Base>> hash;
public:
Base const& get(std::string const&) const;
template<typename Derived> void add(std::string const& name, Derived const& object)
{
std::unique_ptr<Base> copy(new Derived(object));
hash.emplace(std::make_pair(name, std::move(copy)));
}
};
There are a few minor tricks here, as it hash
should be the sole owner of the copy, but it is built externally and therefore needs to be moved. (For extra fantasy, I could add an overload Derived&&
that also removes this copy)
source to share
I would assume that all the classes you must register have a common supertype. For example, if you need to store instances of classes One
, Two
and Three
, you can define a (possibly empty) class Object
from which your class can get:
class Object {}
class One : public Object { /* One member and methods */ }
class Two : public Object { /* Two member and methods */ }
class Three : public Object { /* Three member and methods */ }
If you follow the MSalters question , you can declare A<Object*>
.
If you don't have one supertype (for example, because you can't change One
, Two
or Three
), you can look at Boost. Option . Again, you can declare A<boost::variant<One, Two, Three> >
.
source to share
The first question is, how do you B
know the type of the stored object, and what can it do about it? Perhaps the simplest solution is to simply have one registry for each type. Alternatively, something like
boost::variant
, or you can ensure that all types come from a common base and store a pointer to that. If you actually need to support polymorphism (for example, work on an object without knowing its exact type), I would avoid the pointer solution.
source to share