Darius Duesentrieb
Darius Duesentrieb

Reputation: 847

How can I call every instantiated function of a template function?

Is it somehow possible to call every instantiation of a template function without knowing what will get instantiated at write-code-time?

#include <iostream>

template<typename T>
void print_size_of()
{
    std::cout << sizeof(T) << "\n";
}

int main()
{
    print_size_of<int>();
    print_size_of<double>();

//won't work but maybe it shows what i want to do:
    template<typename T>
    print_size_of<T>();
//is there a syntax so that the compiler replaces that with `print_size_of<int>(); print_size_of<double>();`
}

Upvotes: 3

Views: 716

Answers (2)

llllllllll
llllllllll

Reputation: 16424

This is possible; you need to add some static variable inside the function template body to record those instantiations.

In the code below, every instantiated function will have a static variable, whose constructor will register the function pointer to a global registration center:

std::vector<void(*)()> funcs;

struct helper {
    explicit helper(void (*f)()) { funcs.push_back(f); }
};

template<typename T>
void print_size_of()
{
    static helper _(&print_size_of<T>);
    std::cout << sizeof(T) << "\n";
}

int main()
{
    print_size_of<int>();
    print_size_of<double>();

    std::cout << "All instantiation:\n";

    for ( auto f : funcs ) {
        f();
    }
}

EDIT:

This is not strictly recording instantiation. It only records those being called before. If you instantiate it by other methods like taking its address:

void (*f)() = &print_size_of<short>;

but don't call it, then this function pointer won't be registered.

EDIT2:

In fact, it is possible to faithfully record all instantiations. The key point is to associate the instantiation of the function template to the instantiation of a class template. Then a static member of that class will be guaranteed to initialize before entering main() function.

// this one is to make sure `funcs` is initialized
auto &get_funcs() {
    static std::vector<void(*)()> funcs;
    return funcs;
}

template<void (*f)()>
struct helper {
    helper() { get_funcs().push_back(f); }
    // this is a static class member, whose initialization is before main()
    static helper _ins;
};

template<void (*f)()> helper<f> helper<f>::_ins;

template<typename T>
void print_size_of()
{
    // force instantiation of a class
    const void *_ = &helper<&print_size_of<T>>::_ins;
    std::cout << sizeof(T) << "\n";
}

int main()
{
    print_size_of<int>();
    print_size_of<double>();

    void (*f)() = &print_size_of<short>;

    std::cout << "All instantiation:\n";

    for ( auto f : get_funcs() ) {
        f();
    }
}

Upvotes: 5

Deduplicator
Deduplicator

Reputation: 45674

No, that is not possible.

You can get close by calling every instantiation which was already called once (Use a static variable to register on first call), but that's the best you can do.

Upvotes: 3

Related Questions