Home > OS >  C Iterate over template variable instantiations
C Iterate over template variable instantiations

Time:11-12

Take a look at this:

#include <vector>
#include <iostream>

template<class T>
std::vector<T> vec{};

int main() {
    vec<short>.push_back(5);
    vec<int>.push_back(10);
    vec<long int>.push_back(15);
}

The vec variable is templated, but there is no telling what possible instantiations occurred. In this case it is clear: short, int and long. But what about more complex cases? How do I track template instantiations?

My goal is to be able to iterate over all vec instances. Something like

for (std::any element : vec) {
    delete element; // Or any common logic the types might have (can guarantee with concepts)
}

CodePudding user response:

You might be able to do something if you wrap vec in a function, and have a type-erased "do things to vec<T>" interface.

You will need to specify all the things you want to do to the various vec<T>()s up front.

template <typename T>
concept printable = requires (T t) { std::cout << t; }

template <printable T>
std::vector<T> & vec();

struct vec_printer
{
    vec_printer(std::type_index index) : index(index) {}

    virtual ~vec_printer() = default;
    virtual void print() = 0;
    // etc...

    std::type_index index;
};

struct vec_printer_compare 
{
    using ptr = std::unique_ptr<vec_printer>;
    bool operator(const ptr & lhs, const ptr & rhs){ return lhs->index < rhs->index; }
};

std::set<std::unique_ptr<vec_printer>, vec_printer_compare> vec_printers;

template <printable T>
struct vec_printer_impl
{
    vec_printer_impl() : vec_printer(typeid(T)) {}
    void thing_one() { for (auto & v : vec<T>()) { std::cout << v; } }
};

template <printable T>
std::vector<T> & vec()
{
    vec_printers.emplace(std::make_unique<vec_printer_impl<T>>());
    static std::vector<T> v;
    return v;
}

void print_vecs()
{
    for (auto & printer : vec_printers) { printer->print(); }
}
  • Related