为每个C ++类模板实例执行一次代码

时间:2014-10-13 07:09:29

标签: c++ templates c++11 class-template

好的,这是一个复杂的问题。

我有一个多次实例化的C ++类模板。对于这些实例中的每一个,我都需要执行一个注册一些运算符的函数。在使用该模板实例的第一个对象之前,每个模板实例只需要执行一次(这并不意味着它必须在编译时发生 instanciation时执行)。

最新我手动完成了这项工作。但这是一种痛苦。所以我想自动执行注册功能。

我目前的想法是在构造函数中调用一个受保护的注册方法。然而,每当构造一个类的实例时,这需要(小的)开销。由于经常这样做,我想避免这种开销。

我还尝试使用静态RAII帮助程序成员,但如果没有主动访问静态模板类成员,则不构造静态模板类成员,因此尝试失败。

有没有办法在类模板instanciation上执行代码(通过函数或可能由RAII帮助器类)而没有运行时开销?

1 个答案:

答案 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;
}

Demo

编辑:这实际上有点不安全,因为未指定在不同翻译单元中创建静态对象的顺序,因此例如在std::cout的加速时可能没有Data::Data()(所以不要在那里使用任何静态全局对象)。更安全的方法是在A::A()中调用静态函数,尽管它会引入一些开销:

template<typename T>
class A {
    static void createData() {
        static Data<T> data;
    }
public:
    A() {
        createData();
    }
};