5

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

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

到目前为止,我是手动完成的。但这是一种痛苦。所以我想自动执行注册功能。

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

我还尝试使用静态 RAII 助手成员,但如果未主动访问静态模板类成员,则不会构造它们,因此此尝试失败。

有没有一种方法可以在没有运行时开销的情况下在类模板实例化(通过函数或可能通过 RAII 助手类)上执行代码?

4

1 回答 1

6

您可以添加一个静态数据成员,该成员将在其构造函数和析构函数中执行所需的任何操作。您可以放心地将其定义放入头文件中,因为只要它是模板,它只会被定义一次。唯一的问题是要实例化它,您必须使用它。

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::coutData::Data()一种更安全的方法是在 中调用静态函数A::A(),尽管它会引入一些开销:

template<typename T>
class A {
    static void createData() {
        static Data<T> data;
    }
public:
    A() {
        createData();
    }
};
于 2014-10-13T07:37:23.937 回答