派生类中的显式模板静态成员实例化

ser*_*gej 6 c++ inheritance singleton templates c++11

我正在尝试使用静态成员实现模板类.从模板类派生的类应该被实例化,而不需要编写额外的代码.

这是我天真的(而不是成功的)方法:

Singleton.h:

template <class T> class Singleton {
protected:
  Singleton();
  static T instance_;
}

// explicit instantiation of 'instance_' ???, 
// where 'instance_' is an instance of the derived class
template <class T> T Singleton<T>::instance_;
Run Code Online (Sandbox Code Playgroud)

ConcreteA.h:

class ConcreteA : public Singleton<ConcreteA> {
public:
  ConcreteA();
  void foo();
}
Run Code Online (Sandbox Code Playgroud)

main.c中:

int main() {
  // an instance of ConcreteA should have been created (no extra code)!!!
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

有没有办法强制的实例ConcreteA由刚刚获得ConcreteA的Singleton,而无需编写额外的实例代码?

一个肮脏的解决方法是instance_在ConcreteA构造函数中调用方法,例如:

ConcreteA.c

ConcrereA::ConcreteA { instance_.foo(); }
Run Code Online (Sandbox Code Playgroud)

有更好的解决方法吗?

bog*_*dan 5

基于您自己的“肮脏技巧”,这适用于我测试的所有编译器,并且不需要派生类构造函数中的任何代码:

#include <iostream>

template <class T> class Singleton {
protected:
  Singleton() { instptr_ = &instance_; }
  static T instance_;
private:
  static T* instptr_;
};

template<class T> T Singleton<T>::instance_;
template<class T> T* Singleton<T>::instptr_;

class ConcreteA : public Singleton<ConcreteA> {
public:
  ConcreteA() { std::cout << "ConcreteA constructed.\n"; }
  void foo();
};

int main() {
  //Prints 'ConcreteA constructed.'.
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

instance_ 我对此的理解是,获取odr的地址-使用它,迫使它存在。我必须说,我不能 100% 确定这不会在某些编译器的未来版本中被优化(我在-O2任何地方都对其进行了测试)。

编辑:看起来甚至像这样编写基类构造函数

Singleton() { (void)&instance_; }
Run Code Online (Sandbox Code Playgroud)

就足够了,完全摆脱了instptr_。