C ++模板静态成员构造函数未被调用

时间:2014-02-20 07:09:53

标签: c++ templates visual-c++ static generic-programming

我有两个具有静态成员实例的类的测试用例。第一个使用非模板化样本,而第二个使用通用对象类型。

困境很简单:静态成员的构造函数在main函数之前调用(应该如此),但仅适用于特定的对象类型。泛型类型不会表现出相同的行为。事实上,构造函数根本没有编译。似乎编译器决定完全忽略它作为(不完全合理)优化的手段。

我想知道发生了什么,以及如何使其以最优雅的方式运作。我认为显而易见的答案是:在代码中的某处使用静态成员。我不想这样做,因为除了在构造函数中执行一些“工作”之外,特定类型的情况不使用该静态成员。

代码示例:

//////////////////////////////////////////////
// Specific case
//////////////////////////////////////////////
class CPassive
{
public:
    CPassive()
    {
        printf(" passively called ");
    }
};

class CActive
{
private:
    static CPassive ms_passive;
};
CPassive CActive::ms_passive;
///////////////////////////////////////////////////////////
// GENERIC TYPES
///////////////////////////////////////////////////////////
class CSample
{
public:
    CSample()
    {
        printf("sample ");
    }
};

template <typename T>
class CGenericPassive
{
public:
    CGenericPassive()
    {
        T sample;
        printf(" generic passive .. ");
    }
private:
};

template <typename T>
class CGenericActive
{
private:
    static CGenericPassive<T> ms_passive;
};
template<typename T>
CGenericPassive<T> CGenericActive<T>::ms_passive;

int main(int argc, char** argv)
{
    CActive activeExample;// instantiates the static member
    CGenericActive<CSample> activeExample; // obliterates the static from the class def.
}

1 个答案:

答案 0 :(得分:3)

您希望实例化的每个类模板的每个(非虚拟)成员都需要直接或间接地从非模板代码中引用。仅仅实例化类本身是不够的。

这受标准14.7.1 / 2的约束:

  

除非已经显式实例化或明确专门化了类模板或成员模板的成员,否则在需要成员定义存在的上下文中引用特化时,将隐式实例化成员的特化;特别是,除非静态数据成员本身以需要静态数据成员定义存在的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用)。

在你的情况下,引用CGenericActive构造函数中的成员就足够了(显然你需要编写这个构造函数),如下所示:

CGenericActive()
 {
   // just reference it so it gets instantiated
   (void)ms_passive;
 }

Full live example