Field
сам по себе не является типом, но шаблоном, который может генерировать семейство типов, таких как Field<int>
и Field<double>
. Все эти поля не связаны между собой так, что одно так или иначе получено из другого или такого. Таким образом, вы должны установить некоторую связь между всеми этими сгенерированными типами. Одним из способов является использование общего базового класса, не являющегося шаблоном:
class FieldBase { };
template <typename T>
class Field : public FieldBase {
private:
T value;
DataType<T> type;
};
class Row {
private:
std::map<unsigned long,FieldBase*> column;
};
И рассмотрите возможность использования умного указателя вместо этого необработанного указателя в коде. Во всяком случае, теперь проблема в том, что информация о типе теряется - указываете ли вы на Field<double>
или на Field<int>
- больше не известно и может быть обнаружено только при хранении какого-либо флага типа в базе, который устанавливается шаблонным производным классом - или запрашивая RTTI, используя
dynamic_cast<Field<int>*>(field) != 0
Но это ужасно. Тем более, что в том, что вы хотите, есть значение семантическое. Т.е. вы хотели бы иметь возможность скопировать вашу строку, и она будет копировать все поля в ней. И вы хотели бы получить удвоение при хранении двойника - без предварительного использования RTTI, чтобы взломать ваш путь к производному типу.
Один из способов сделать это - использовать дискриминационный союз. Это в основном объединение для некоторых произвольных типов и, кроме того, флаг типа, который хранит то, какое значение в настоящий момент хранится в этом поле (например, double, int, ...). Например:
template <typename T>
class Field {
private:
T value;
DataType<T> type;
};
class Row {
private:
std::map<unsigned long,
boost::variant< Field<int>, Field<double> > >
column;
};
Boost :: Вариант делает всю работу за вас. Вы можете использовать посещение, чтобы вызвать функтор, используя правильную перегрузку. Взгляните на его руководство