好的,这是一个复杂的问题。
我有一个多次实例化的C ++类模板。对于这些实例中的每一个,我都需要执行一个注册一些运算符的函数。在使用该模板实例的第一个对象之前,每个模板实例只需要执行一次(这并不意味着它必须在编译时发生 instanciation时执行)。
最新我手动完成了这项工作。但这是一种痛苦。所以我想自动执行注册功能。
我目前的想法是在构造函数中调用一个受保护的注册方法。然而,每当构造一个类的实例时,这需要(小的)开销。由于经常这样做,我想避免这种开销。
我还尝试使用静态RAII帮助程序成员,但如果没有主动访问静态模板类成员,则不构造静态模板类成员,因此尝试失败。
有没有办法在类模板instanciation上执行代码(通过函数或可能由RAII帮助器类)而没有运行时开销?
答案 0 :(得分:6)
您可以添加一个静态数据成员,该成员将执行其构造函数和析构函数中所需的任何内容。您可以放心地将其定义放入头文件中,因为只要它是模板,它就只定义一次。唯一的问题是要实例化它,你必须odr-use它。
template <typename T>
class Data {
public:
Data() {
std::cout << "creating Data<" << typeid(T).name() << '>' << std::endl;
}
~Data() {
std::cout << "destroying Data<" << typeid(T).name() << '>' << std::endl;
}
};
template<typename T>
class A {
static Data<T> data;
public:
A() {
// this is necessary for data to be instantiated
(void)data;
}
};
// This also should be in a header
template<typename T>
Data<T> A<T>::data;
int main(){
A<int> aInt;
A<int> aInt2;
A<float> aFloat;
}
编辑:这实际上有点不安全,因为未指定在不同翻译单元中创建静态对象的顺序,因此例如在std::cout
的加速时可能没有Data::Data()
(所以不要在那里使用任何静态全局对象)。更安全的方法是在A::A()
中调用静态函数,尽管它会引入一些开销:
template<typename T>
class A {
static void createData() {
static Data<T> data;
}
public:
A() {
createData();
}
};