Re[4]: Шаблон Property Manager
От: _Macintosh_ Израиль  
Дата: 26.01.04 20:34
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Описал бы не так узко, а big picture, может нашлось бы более интересное решение твоей задачи.


Я старался акцентировать внимание на вопросе, который, собственно, теоретический. Хотя, по большому счету, это почти вся задача (мелкомасштабный я какой-то ). По историческим причинам в проекте, в котором я учавствую, принято выставлять наружу из библиотек С-интерфейс. И чтобы не раздувать интерфейс, всякие параметры передаются через Get/SetParameter(long paramID, void* dataStruct, size_t dataStructSize).
Со стороны библиотеки сидит switch по ID, переадресующий вызов куда следует. В общем, классика . Причем, набор параметров меняется в зависимости от режима работы библиотеки. Я хочу это автоматизировать примерно так:

Шаблон для определения внутреннего(библиотечного) типа параметра
template <class SimpleParamType, int ParamID>
struct SParam
{
    // внешний(пользовательский) тип параметра
    typedef SimpleParamType TUserParamType;
    // ID для доступа
    enum {k_ParamID = ParamID};
    TUserParamType m_Param;
    TUserParamType GetUserParam() const
    {
       return m_Param;
    }
};

typedef SParam<float, 1> SParam1;
typedef SParam<long, 2> SParam2;


Это конкретный класс, определяющий набор параметров для конкретного режима работы.
class CParamsHolder
{
  public:
    // текущий набор параметрав
    typedef TYPELIST_2(SParam1, SParam2) TParamList;

    long GetParam(SParam1& param) const
    {
      ...
    }

    long GetParam(SParam2& param) const
    {
      ...
    }
};


Это шаблон диспетчера, конкретизирующийся текущим набором параметров. Шаблон TypelistToFuncMap описан в предыдущем посте.
class IParamsManager
{
   long GetParameter(long paramID, void* buf, size_t bufSize) = 0;
};

template <class ParamsHolder>
class CParamsManager : piblic IParamsManaget
{
    public:
      typedef (CParamsManager<ParamsHolder>::*TCall)(long paramID, void* buf, size_t bufSize);
      typedef TCall TCallMap[k_TotalParams]; //для упрощения кода
    private:
      ParamsHolder m_ParamsHolder;
      TCallMap m_CallMap;
    public:
      
      CParamsManager()
      {
         memset(m_CallMap, 0, sizeof(m_CallMap));

         // Конвертируем список типов в набор конкретизаций GetUserParameter<...> 
         TypelistToFuncMap<ParamsHolder::TParamList, 
                            CParamsManager<ParamsHolder> 
                           >::Convert(m_CallMap);
      }

      template <class InternalParamType>
      long GetUserParameter(long paramID, void* buf, size_t bufSize)
      {
         long retVal = -1;
         if(bufSize == sizeof(InternalParamType::TUserParamType))
         {
            InternalParamType param;
            retVal = m_ParamsHolder.GetParam(param);
            *(static_cast<InternalParamType::TUserParamType*>(buf)) = param.GetUserParam();
         }
         return retVal;
         
      }
      
      long GetParameter(long paramID, void* buf, size_t bufSize)
      {
         TCall theCall = CallMap[paramID];
         if(0 == theCall)
            return -1;
         else
            return (this->*theCall)(buf, bufSize);
      }

};

Ну и все, вроде. Если кто-то прочитает эту строчку, то наверняка предложит более красивое решенее .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.