Как передать тип в С++???

Julia79

Есть следующая конструкция:
enum
{
TypeInt
TypeDouble
...
} TypeStruct;

которая определена в используемой мной библиотеке. Эта библиотека создает объект, и возвращает в переменную
int objHandle ,
где objHandle идентификатор объекта. Объект содержит большое число переменных всех типов определенных в TypeStruct, где каждая переменная имеет некоторый уникальный таг. Можно посмотреть тип переменной через функцию
 TypeStruct GetVarType(int &objHandle,long int varjTag);  

Можно получить значение каждой переменной через набор функций
 GetValToIntint &objHandle,unsigned long  varTag,int &val);
GetValToDoubleint &objHandle,unsigned long int varTag,double &val);

и т.п.
Я написал шаблонные функции типа
 
template <class T> GetVal(int &objHandle,unsigned long objTag,T &val)
template <class T> SetVal(int &objHandle,unsigned long objTag,const T &val)

Теперь есть некий шаблонный алгоритм

template <class T> ReadModifyAndSaveVal(int &objHandle,unsigned long tag);
который получает в качестве входного параметра таг переменной, читает её используя GetVal<T>, что-то с ней делает, и куда-то её записывает используя SetVal<T>. Проблема в том, чтобы элегантно передать тип переменной для инициализации шаблона используя метод GetVarType(int &objHandle,long int varTag вроде

ReadModifyAndSaveVal< GetVarType(int &objHandle,long int varTag)>(int &objHandle,unsigned long tag);
,
без того чобы каждый раз писать

switch(GetVarType(int &objHandle,long int varTag
{
case IntType:
ReadModifyAndSaveVal<int>(int &objHandle,unsigned long tag);
break;
case DoubleType:
ReadModifyAndSaveVal<double>(int &objHandle,unsigned long tag);
break;
...
}

каждый раз при вызове алгоритма. Как можно это сделать наиболее эффективно средствами С++, при условии что я не могу менять исходный код библиотеки и её методы?

okis

Почему бы switch не написать один раз в нешаблонной функции? Зачем вообще применять здесь шаблоны?

SEMEN73

Совсем избавиться от switch или аналогов не получится, его можно только спрятать.
Если код алгоритма для разных типов отличается, можно поступить так:

class BaseAlg
{
public:
void run(int &objHandle, unsigned long tag)
{
switch(GetVarType(objHandle, varTag
{
case IntType:
this->runInt(objHandle, tag);
break;
case DoubleType:
this->runDouble(objHandle, tag);
break;
//...
}
}
private:
virtual void runInt(int &objHandle, unsigned long tag) = 0;
virtual void runDouble(int &objHandle, unsigned long tag) = 0;
//...
};

class MyAlg : public BaseAlg
{
private:
virtual void runInt(int &objHandle, unsigned long tag) { /* Code for Int here */}
virtual void runDouble(int &objHandle, unsigned long tag) { /* Code for Double here */ }
//...
};

В противном случае виртуальные функции также можно сделать шаблонными.

karkar

Ты хочешь в compile time использовать run time значение?
Шаблоны подставляются при компиляции, а результат твоей GetVarType известен лишь при исполнении.
Совершить задуманное просто - нужно лишь перейти с С++ на Agda2. ;)

iravik

который получает в качестве входного параметра таг переменной, читает её используя GetVal<T>, что-то с ней делает, и куда-то её записывает используя SetVal<T>
в рамках оффтопа: разбей эту функцию на несколько, а то она слишком много всего делает

elenangel

switch(GetVarType(int &objHandle,long int varTag
{
case IntType:
ReadModifyAndSaveVal<int>(int &objHandle,unsigned long tag);
break;
case DoubleType:
ReadModifyAndSaveVal<double>(int &objHandle,unsigned long tag);
break;
...
}

сделай мапу enum->указатель на функцию

enum TypeTag
{
TypeInt
TypeDouble
...
};


typedef (*GetValFunctionint &,unsigned long ,T &);

map<TypeTag,GetValFunction> getVal;

typedef (*SetValFunctionint &,unsigned long , const T &);

map<TypeTag,SetValFucntion> setVal;


далее, где-то в программе напиши

getVal[TypeInt] = &GetVal<int>;
getVal[TypeDouble] = &GetVal<double>

setVal[TypeInt] = &SetVal<int>;
setVal[TypeDouble] = &SetVal<double>

ну и наконец,

template <class T> ReadModifyAndSaveVal(int &objHandle,unsigned long tag)
{
T someVar;
(*getVal[tag]objHandle,tag,someVar);
}

Maurog


typedef (*GetValFunctionint &,unsigned long ,T &);
map<TypeTag,GetValFunction> getVal;

неувязочка в букве T :o

elenangel

блин, действительно
тогда я даже не знаю что делать, кроме switch

Maurog

мне нравится такой подход
применительно к поставленной задаче я бы переписал его так:

class SuperVariant
{
public:
SuperVariant(int &objHandle, unsigned long tag)
: m_ObjHandle(objHandle)
, mTag(tag)
{
}

TypeStruct GetValueType const
{
return GetVarType(m_ObjHandle, m_Tag);
}

template<typename T>
T GetValue const
{
return GetVal<T>(m_ObjHandle, m_Tag);
}

template<typename T>
void SetValue(const T& newValue)
{
SetVal<T>(m_ObjHandle, m_Tag, newValue);
}

private:
int& m_ObjHandle;
unsigned long m_Tag;
};

class BaseAlg
{
public:
explicit BaseAlg(SuperVariant& value)
: m_Value(value)
{
}

//do not call from constructor
void ReadModifyAndSaveVal
{
switch (m_Value.GetValueType
{
case IntType:
m_Value.SetValue<int>(ModifyInt(m_Value.GetValue<int>
break;
case DoubleType:
m_Value.SetValue<double>(ModifyDouble(m_Value.GetValue<double>
break;
//...
}
}

private:
virtual int modifyInt(int oldValue) = 0;
virtual double modifyDouble(double oldValue) = 0;
//...
private:
SuperVariant& m_Value;
};

class MyAlg : public BaseAlg
{
private:
virtual int modifyInt(int oldValue) { /* Code for Int here */}
virtual double modifyDouble(double oldValue) { /* Code for Double here */ }
//...
};
Оставить комментарий
Имя или ник:
Комментарий: