Очередной синглтон
От: syomin  
Дата: 08.11.07 14:56
Оценка: :)
День добрый!
Смастерил очередной велосипед на вечную тему синглтона. Сразу отмечу, что задача получения потокобезопасной реализации не ставилась. Выкладываю с целью услышать конструктивную критику :).

// Файл singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H

#include <stdexcept>

#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>

// Данный шаблон предназначен для реализации синглтонов, у которых операция
// получения ссылки на объект (метод instance()) отделена от операции создания
// объекта (метод create()). Такой подход позволяет делать синглтонами объекты,
// требующие передачи параметров в конструктор.
template<typename T, typename Arg1>
class Singleton : public boost::noncopyable {
public:
    // Создать объект.
    static void create(Arg1 arg1)
    {
        if(instance_)
            throw std::logic_error("Повторное создание синглтона");
        instance_.reset(new T(arg1));
    }

    // Получить ссылку на объект, созданный ранее с помощью create().
    static T &instance()
    {
        if(!instance_)
            throw std::logic_error("Обращение к неинициализированному синглтону");
        return *static_cast<T*>(instance_.get());
    }

protected:
    // Делаем конструктор защищенным, чтобы нельзя было напрямую создать
    // экземпляр Singleton<>.
    Singleton() {}

    virtual ~Singleton() {}

private:
    // Тип класса.
    typedef Singleton<T, Arg1> ThisType;

    // Указатель на экземпляр класса.
    typedef boost::scoped_ptr<ThisType> Instance;
    static Instance instance_;

    friend void boost::checked_delete<>(ThisType * x);
};

template<typename T, typename Arg1>
typename Singleton<T, Arg1>::Instance Singleton<T, Arg1>::instance_;

#endif


Использование:
#include "singleton.h"

class MyObj : public Singleton<MyObj, int> {
private:
    // Конструктор.
    explicit MyObj(int foo);

    // Нужно для корректоной работы синглтона.
    friend class Singleton<MyObj, int>;
    ~MyObj() {}
};

...
MyObj::create(128);
MyObj::instance();
...
// А вот такой фокус не пройдет:
delete &MyObj::instance();
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.