Здравствуйте, 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);
}
};
Ну и все, вроде. Если кто-то прочитает эту строчку, то наверняка предложит более красивое решенее

.