Как передать в Синглтон Майерса параметры конструктора?
От: Аноним  
Дата: 31.07.06 17:41
Оценка:
Есть такой синглтон:

template <typename BaseT>
class Singleton
    : public BaseT
    , private boost::noncopyable
{
private:
    Singleton()
    {
    }

    ~Singleton()
    {
    }

public:
    static Singleton& instance()
    {
        static Singleton _instance;
        return _instance;
    }
};


Как модифицировать этот класс, чтобы он создавал экземпляр _instance, если у BaseT нет конструктора по умолчанию? Например, в качестве класса BaseT я использую класса Trace (или Log) для вывода отладочной информации, в конструктор которого передаю имя файла для лога. Используется RAII, в конструкторе файл открывается, в диструкторе закрывается.

Решение с передачей аргументов в функцию instance выглядит не очень красивым, так как синглтон создается одни раз по определению, дык что теперь при каждом вызове эти аргументы передавать...

Помогите пожалуйста найти решение.
Re: Как передать в Синглтон Майерса параметры конструктора?
От: einstein  
Дата: 31.07.06 17:54
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>template <typename BaseT>
А>class Singleton
А>    : public BaseT
А>    , private boost::noncopyable
А>{
А>private:
А>    Singleton()
А>    {
А>    }

А>    ~Singleton()
А>    {
А>    }

А>public:
А>    static Singleton& instance(Singleton* p = new Singleton() )
А>    {
А>        static std::auto_ptr<Singleton> _instance ( p );
А>        return _instance.get();
А>    }
А>};
А>


А>Как модифицировать этот класс, чтобы он создавал экземпляр _instance, если у BaseT нет конструктора по умолчанию? Например, в качестве класса BaseT я использую класса Trace (или Log) для вывода отладочной информации, в конструктор которого передаю имя файла для лога. Используется RAII, в конструкторе файл открывается, в диструкторе закрывается.


X& x = XSingleton<X>::instance(new X(....));

В данном случае Singleton будет следить за созданным вами объектом (то есть мы передаем владение).
Re[2]: Как передать в Синглтон Майерса параметры конструктор
От: einstein  
Дата: 31.07.06 18:09
Оценка:
Здравствуйте, einstein, Вы писали:

E>Здравствуйте, Аноним, Вы писали:


А>>
А>>template <typename BaseT>
А>>class Singleton
А>>    : public BaseT
А>>    , private boost::noncopyable
А>>{
А>>private:
А>>    Singleton()
А>>    {
А>>    }

А>>    ~Singleton()
А>>    {
А>>    }

А>>public:
А>>    static Singleton& instance(Singleton* p = 0)
А>>    {
           static std::auto_ptr<Singleton> _instance;
А>>        if (p) _instance.reset(p);
           else
           {
              if (!_instance) _instance.reset(new Singleton);
           }
А>>        return _instance.get();
А>>    }
А>>};
А>>



X& x = Singleton<X>::instance(new X(....));



хм.. ошибочка вышла.
Вот так вроде будет то, что хотелось.
Правда потоконебезопасно, впрочем как и исходный синглтон Мейерса.
Re: Как передать в Синглтон Майерса параметры конструктора?
От: np9mi7 Россия  
Дата: 31.07.06 19:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>...в конструкторе файл открывается, в деструкторе закрывается.


А>Помогите пожалуйста найти решение...


На то он и Синглтон Майерса чтоб с конструктором по умолчанию работать;

А не проще сделать метод, типа Open Close? И свойство IsOpened?

Или, что ещё проще:
const char * GetFileName ();

class Log
{
     public:
          Log ()
          {
               Open (GetFileName ());
          }
};
Может так можно?

Ну если нельзя, то тогда это про стратегии создания, удаления и.т.д в итоге получим Loki::SingletonHolder;
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re: Как передать в Синглтон Майерса параметры конструктора?
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 01.08.06 08:46
Оценка:
Здравствуйте, <Аноним>, Вы писали:

Проще всего так:
// это ваш исходный класс без конструктора по-умолчанию
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: Как передать в Синглтон Майерса параметры конструктора?
От: Кодт Россия  
Дата: 01.08.06 09:37
Оценка:
Здравствуйте, <Аноним>, Вы писали:

Только не Майерса, а Мейерса.

Поскольку конструируется такой синглетон по первому требованию, то есть, неизвестно в каком вызове 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; // должны быть установлены до первого вызова instance
    static Foo make_object() { return Foo(Bar(x,y,z)); }
};
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: Как передать в Синглтон Майерса параметры конструктора?
От: Bachata Россия  
Дата: 04.10.06 12:28
Оценка:
Если нужно просто сделать какой-то класс singleton'ом, то не обязательно пользоваться singleton'ом Мейерса.
Можно воспользоваться библиотекой lib-global.
Она реализует те же задачи, что и паттерн Singleton, но плюс к этому позволяет работать
с классами, у которых нет конструктора по умолчанию.
Re[2]: Как передать в Синглтон Майерса параметры конструктор
От: Bell Россия  
Дата: 04.10.06 13:46
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Только не Майерса, а Мейерса.


Тут есть несколько иное мнение
Автор: alexkro
Дата: 06.03.03
Любите книгу — источник знаний (с) М.Горький
Re: Как передать в Синглтон Майерса параметры конструктора?
От: Sm0ke Россия ksi
Дата: 05.10.06 10:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть такой синглтон:


А>
А>template <typename BaseT>
А>class Singleton
А>    : public BaseT
А>    , private boost::noncopyable
А>{
А>private:
А>    Singleton()
А>    {
А>    }

А>    ~Singleton()
А>    {
А>    }

А>public:
А>    static Singleton& instance()
А>    {
А>        static Singleton _instance;
А>        return _instance;
А>    }
А>};
А>


А>Как модифицировать этот класс, чтобы он создавал экземпляр _instance, если у BaseT нет конструктора по умолчанию? Например, в качестве класса BaseT я использую класса Trace (или Log) для вывода отладочной информации, в конструктор которого передаю имя файла для лога. Используется RAII, в конструкторе файл открывается, в диструкторе закрывается.


А>Решение с передачей аргументов в функцию instance выглядит не очень красивым, так как синглтон создается одни раз по определению, дык что теперь при каждом вызове эти аргументы передавать...


А>Помогите пожалуйста найти решение.


Явная специализация параметров шаблона


  //  singleton
template <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;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.