보통 다른 곳에서는 상속기반의 CRTP로 싱글톤을 구현하지만, 이와 약간 다르게 구현이 되어 있다.
#ifndef ANDROID_UTILS_SINGLETON_H #define ANDROID_UTILS_SINGLETON_H namespace android { templateclass Singleton { public: static T& getInstance() { T* instance = sInstance; if(instance == 0) { instance = new T(); // Call Default Constructor sInstance = instance; } return *instance; } protected: ~Singleton(){} Singleton(){} private: Singleton(const Singleton&); // Prohibit Copy Constructor Singleton& operator= (const Singleton&); // Prohibit Copy Constructor static T* sInstance; // Static Instance }; #define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \ template class Singleton< TYPE >; \ // Default Template template<> TYPE* Singleton< TYPE >::sInstance(0); // Specialization // ----------------------------------------------- }; // namespace android #endif
ANDROID_SINGLETON_STATIC_INSTANCE 매크로를 이용해서 template 클래스(template class Singleton<TYPE>) 와 특수화 클래스(template<> TYPE* Singleton<TYPE>::sInstance(0) )를 만든다.
여기서 특수화는 부분 특수화가 아닌 완전 특수화이다. 부분 특수화이든, 완전 특수화이든 특수화를 하려면 선언일지라도 특수화하지 않은 template 형태(흔히 primary라고 부른다)가 필요하다. 그래서 template class Singleton<TYPE>; 이 선언형태로 들어간다.
정적 객체를 얻어올시에는 매크로를 이용하여 한번 선언한 뒤에
Test t = Singleton::getInstance();
위와 같이 일반 값이나 참조의 형태로 받으면 된다.
getInstance() 의 반환값의 형태가 참조이기 때문에 만약 포인터 변수로 받을시에는 &연산자가 필요하다.
또한 Test 클래스는 기본 생성자(Default Constructor)를 가져야 한다는 제약이 걸려 있다. 만약 인수를 받는 생성자로 호출을 원한다면, 템플릿 클래스를 수정하여야 한다.