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:

5 Replies to “Templates in STL containers”

  1. 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

  2. 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;
    }

Leave a Reply