Storing template classes in STL containers is tricky If
v is a
std::vector and
TC is a template class, how can we do the following:
The trick is two-fold: 1) we need a non-template base class (let’s call it NTB) and 2) we need to store pointers to the non-template base class in the STL container. Like this:
Complete listing:
There is a memory leak in your “trick”
==5022== HEAP SUMMARY:
==5022== in use at exit: 48 bytes in 3 blocks
==5022== total heap usage: 7 allocs, 4 frees, 72,808 bytes allocated
==5022==
==5022== LEAK SUMMARY:
==5022== definitely lost: 48 bytes in 3 blocks
yes I know. it is an example of how to store T’s in containers. a user can figure out that the content of the vector needs deleting
better now?
This is what I like to call the heterogeneous container problem. If you use templates enough, you’re sure to run into it! In the past I have solved it in one of two ways:
1) vector of variants
using variant_type = std::variant<TC, TC, TC>;
using vector_type = std::vector;
vector_type v;
v.push_back(TC(‘x’));
v.push_back(TC(1));
v.push_back(TC(3.14));
for (auto& it : v) {
std::visit(v, [](auto& item) {
item.doWork();
});
}
v.clear();
2) “sparse” (per-type) collections
If you don’t truly need each type to be in the same list, you can make each class maintain it’s own list. This works better for things like queuing async operations. You can also combine it with static dispatch.
template
class TC {
public:
TC(T t) : m_T(t) {}
void doWork() { cout << m_T << endl; }
private:
static std::vector<TC> m_v;
T m_T;
};
TC::queue(TC(‘x’));
TC::queue(TC(1));
TC::queue(TC(3.14));
std::array<std::function<void()>, 3> qs {
&TC::completeAllWork,
&TC::completeAllWork,
&TC::complateAllWork
};
for (std::size_t i=0; i<qs.size(); i++) {
qsi;
}
For inline code use back ticks ‘`’ and for clode blocks use pre tag “< pre >” and “< / pre >”