以某种方式可以调用模板函数的每个实例化,而不知道在写代码时会实例化什么?
#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>();`
}
答案 0 :(得分:4)
这是可能的;你需要在函数模板体中添加一些静态变量来记录那些实例。
在下面的代码中,每个实例化的函数都有一个静态变量,其构造函数将函数指针注册到全局注册中心:
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();
}
}
修改强>
这不是严格记录实例化。它只记录之前调用的那些。如果你通过其他方法实例化它,比如取其地址:
void (*f)() = &print_size_of<short>;
但是不要调用它,那么这个函数指针就不会被注册。
<强> EDIT2:强>
事实上,可以忠实地记录所有实例。关键点是将函数模板的实例化与类模板的实例化相关联。然后,在保证输入main()
函数之前,将保证该类的静态成员初始化。
// 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();
}
}
答案 1 :(得分:3)
不,这是不可能的。
你可以通过调用已经被调用过一次的每个实例来接近(使用静态变量在第一次调用时注册),但这是你能做的最好的。