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(); }
}