I would like to have a container that can ingest an object, and store different parts of it into different internal containers.
Something like this:
// Pseudo-code
template<typename A, typename B, typename C>
class Container {
std::vector<B> vb;
std::vector<C> vc;
public:
void push_back(const A &a) {
vb.push_back(a);
vc.push_back(a);
}
};
class AA {
int a;
std::string s;
};
class BB {
int a;
};
class CC {
std::string s;
};
Container<AA, BB, CC> cont;
AA aa;
cont.push_back(aa);
I would like object vb
to get what is in common between classes A an B (slicing), and the same for object vc
.
Ideally, classes AA, BB and CC should not be in a hierarchical relation. I would like the compiler to be able to match the members by their type.
I would prefer a solution with small performance penalties.
Your pseudocode container already works in the case where AA
inherits BB
and CC
, because slicing allows implicit conversion from derived to base. However, your implementation isn't limited to such cases. All that is required is for AA
to be implicitly convertible to both BB
and CC
. Inheritance is sufficient for that, but not a requirement.
You can make a class convertible to others by defining conversion operators:
struct AA {
operator BB() const { return {a}; }
operator CC() const { return {s}; }
int a;
std::string s;
};
Alternatively, you can add a converting constructor to BB
and/or CC
if you would prefer the dependency to go the other way:
struct BB {
BB(const AA& aa) : a(aa.a) {}
int a;
};
Do note however, that narrowing implicit conversions such as this may cause certain bugs to go unnoticed.