如何调用模板函数的每个实例化函数?

Dar*_*ieb 3 c++ templates instantiation template-meta-programming

是否可以以某种方式调用模板函数的每个实例,而又不知道在写代码时将实例化什么?

#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>();`
}
Run Code Online (Sandbox Code Playgroud)

lll*_*lll 5

这个有可能; 您需要在函数模板主体内添加一些静态变量以记录这些实例化。

在下面的代码中,每个实例化的函数都将有一个静态变量,其构造函数会将函数指针注册到全局注册中心:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

这不是严格记录实例化。它仅记录那些之前被调用的。如果通过其他方法(例如获取其地址)实例化它:

void (*f)() = &print_size_of<short>;
Run Code Online (Sandbox Code Playgroud)

但不要调用它,则不会注册此函数指针。

编辑2:

实际上,可以忠实记录所有实例。关键是将功能模板的实例与类模板的实例相关联。然后,将确保该类的静态成员在进入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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这只会在第一次调用该函数时进行注册。 (2认同)