Авто-регистрация членов класса в самом классе.
От: MaxEd Россия http://www.dhost.info/msiu/
Дата: 26.01.11 07:18
Оценка:
Хочется такую штуку, чтобы можно было написать примерно следующее:

class SomeClass : MemberHolder
{
    TMember<int> m1;
    TMember<std::string> m2;
    TMember<SomeOtherClass> m3;
public:
    void SomeFunc()
    {
        MemberList & l = MemberHolder::GetMemberList();
        // Далее, допустим, итерация по l и какое-нибудь действие
    }
};


При этом, хочется, чтобы НЕ НАДО было упомянать TMember'ов в конструкторе, т.е. не подходят решения вида

class SomeClass : MemberHolder
{
    TMember<int> m1;
    TMember<std::string> m2;
    TMember<SomeOtherClass> m3;
public:
    SomeClass()
        : m1( this )
        , m2( this )
        , m3( this )
};


Подскажите, есть ли хороший способ так сделать в текущем стандарте, или при помощи новых фич C++0x? Я пока изобрёл мега-извращённый способ, который страдает полным отсутствием thread-safety и наличием неявных, но очень опасных ограничений:

class TMember;

class BaseHolder
{
public:
    void RegisterMember( TMember *m ) {...} // добавляем мембера, например, в список
}

class RegistrationHelper
{
    BaseHolder *m_pCurrent;
public:
    void SetCurrentHolder( BaseHolder *pCurrent ) { m_pCurrent = pCurrent; }
    void RegisterMember( TMember *m ) { if ( m_pCurrent ) m_pCurrent->RegisterMember( m ); }
};

template<typename T, RegistrationHelper *helper>
class TMember
{
    T m_value;
public:
   TMember()
   {
       helper->Register( this );
   }
};

class MemberContainer : public BaseHolder
{
protected:
    static RegistrationHelper helper; // Где-то в каком-то cpp его надо инициализировать
public:
    MemberContainer()
    {
        helper.SetCurrentHolder( this );
    }
};

class SomeClass : MemberContainer
{
    TMember< int, &helper > m_member1;
    TMember< WhatEver, &helper > m_member2;
public:
    SomeClass(){}
};


Подозреваю, что сей метод достоин TheDailyWTF, но как лучше — не соображу.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.