Как модифицировать этот класс, чтобы он создавал экземпляр _instance, если у BaseT нет конструктора по умолчанию? Например, в качестве класса BaseT я использую класса Trace (или Log) для вывода отладочной информации, в конструктор которого передаю имя файла для лога. Используется RAII, в конструкторе файл открывается, в диструкторе закрывается.
Решение с передачей аргументов в функцию instance выглядит не очень красивым, так как синглтон создается одни раз по определению, дык что теперь при каждом вызове эти аргументы передавать...
Помогите пожалуйста найти решение.
Re: Как передать в Синглтон Майерса параметры конструктора?
А>Как модифицировать этот класс, чтобы он создавал экземпляр _instance, если у BaseT нет конструктора по умолчанию? Например, в качестве класса BaseT я использую класса Trace (или Log) для вывода отладочной информации, в конструктор которого передаю имя файла для лога. Используется RAII, в конструкторе файл открывается, в диструкторе закрывается.
X& x = XSingleton<X>::instance(new X(....));
В данном случае Singleton будет следить за созданным вами объектом (то есть мы передаем владение).
Re[2]: Как передать в Синглтон Майерса параметры конструктор
Здравствуйте, Аноним, Вы писали:
А>...в конструкторе файл открывается, в деструкторе закрывается.
А>Помогите пожалуйста найти решение...
На то он и Синглтон Майерса чтоб с конструктором по умолчанию работать;
А не проще сделать метод, типа OpenClose? И свойство IsOpened?
Или, что ещё проще:
const char * GetFileName ();
class Log
{
public:
Log ()
{
Open (GetFileName ());
}
};
Может так можно?
Ну если нельзя, то тогда это про стратегии создания, удаления и.т.д в итоге получим Loki::SingletonHolder;
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re: Как передать в Синглтон Майерса параметры конструктора?
// это ваш исходный класс без конструктора по-умолчаниюclass Logger
{
public:
Logger(const std::string & name);
...
};
// добавим ему этот конструкторclass MyLogger
: public Logger
{
MyLogger(): Logger("c:/log.txt") {}
};
typedef Signleton<MyLogger> LogSingleton; // далее используем уже новый класс
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Как передать в Синглтон Майерса параметры конструктора?
Поскольку конструируется такой синглетон по первому требованию, то есть, неизвестно в каком вызове instance() в программе, — то имеются два выхода:
1) использовать класс-потомок или адаптер, чей дефолтный конструктор делает всё что нужно
template<class Face, class Impl=Base>
struct Singleton // а зачем Singleton наследовать от базы - я не понимаю
{
static Face& instance()
{
Impl impl;
return impl;
}
};
struct Foo
{
Foo(Bar);
};
struct FooDerived : Foo
{
FooDerived() : Foo(make_bar()) {}
};
struct FooProxy : noncopyable
{
auto_ptr<Foo> foo;
FooProxy()
{
Bar bar;
bar.init();
.....
foo = new Foo(bar);
.....
}
operator Foo&() { return *foo; }
};
2) использовать политику (фабрику объектов)
template<class Obj, class CreationPolicy=DefaultCreationPolicy<Obj> >
struct Singleton
{
static Obj& instance()
{
Obj& ref = Policy::make_object();
// при желании, здесь можно сделать потокобезопасный код с двойной проверкой
// и прочую обвескуreturn ref;
}
};
template<class Obj>
struct DefaultCreationPolicy
{
static Obj make_obj() { return Obj(); }
};
struct FooPolicy1 // фабрика объектов
{
static Foo make_object() { ..... return Foo(bar); }
};
struct FooPolicy2 // фактически, тот же синглетон Мейерса - только в самом простом его исполнении
{
static Foo& make_object() { ..... static Foo foo(bar); return foo; }
};
Через политику можно передавать параметры в конструктор
struct FooPolicy
{
static int x, y, z; // должны быть установлены до первого вызова instancestatic Foo make_object() { return Foo(Bar(x,y,z)); }
};
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: Как передать в Синглтон Майерса параметры конструктора?
Если нужно просто сделать какой-то класс singleton'ом, то не обязательно пользоваться singleton'ом Мейерса.
Можно воспользоваться библиотекой lib-global.
Она реализует те же задачи, что и паттерн Singleton, но плюс к этому позволяет работать
с классами, у которых нет конструктора по умолчанию.
Re[2]: Как передать в Синглтон Майерса параметры конструктор
А>Как модифицировать этот класс, чтобы он создавал экземпляр _instance, если у BaseT нет конструктора по умолчанию? Например, в качестве класса BaseT я использую класса Trace (или Log) для вывода отладочной информации, в конструктор которого передаю имя файла для лога. Используется RAII, в конструкторе файл открывается, в диструкторе закрывается.
А>Решение с передачей аргументов в функцию instance выглядит не очень красивым, так как синглтон создается одни раз по определению, дык что теперь при каждом вызове эти аргументы передавать...
А>Помогите пожалуйста найти решение.
Явная специализация параметров шаблона
// singletontemplate <class T>
class single
{
protected:
single()
{}
~single()
{}
typedef single<T> self_single;
typedef T self;
public:
static T & get_single(); // получить экземплярчик
};
template <class T>
inline T & single<T>::get_single()
{
static T instance;
return instance;
}
// применение singleton'а на этом классеclass something :
public single<something>
{
friend class self_single;
private:
int i;
something(int new_i) : i(new_i)
{}
~something()
{}
};
// полная специализация методаtemplate <>
inline something & something::self_single::get_single()
{
static self instance(10); // параметрыreturn instance;
}