Создание бинарного дерева, содержащего данные разных типов
У меня есть следующая структура:
template <typename T>
struct Attribute
{
Attribute() {
name = "EmptyAtribute";
value = NULL;
}
Attribute(string name,T value) {
this->name = name;
this->value = value;
}
string name;
T value;
};
Подобие самой обыкновенной пары. Получается, каждый атрибут имеет поле name (которое у всех строка) и шаблонное value.
Теперь мне необходимо создать какую-либо динамическую структуру данных, которая эти атрибуты будет хранить - class AttributeList.
Идея была использовать бинарное дерево, где поле name будет ключом, а value - значением. (Я посчитал, что дерево использовать лучше, так как я часто буду обращаться к атрибутам именно по их ключу - полю name).
Получается, узел дерева содержит в себе два указателя (pLeft, pRight) и, непосредственно, объект структуры Attribute, но так как структура Attribute шаблонная, то и узел, а значит и само дерево должны быть шаблонными.
Прошу, пожалуйста, помочь мне создать дерево, где я смогу хранить Атрибуты с разными типами поля value. Чтобы тип value я мог указывать при добавлении нового узла.
P.S. Я сделал метод add вместо всего класса AttributeList шаблонным, но у меня возникли проблемы с созданием root-узла. Я хочу иметь возможность создать объект класса AttributeList в тот момент, пока я ещё не знаю, чем буду его заполнять.
Ответы (2 шт):
Я правильно понимаю, что вы хотите хранить разные типы значений одновременно? тогда я вижу два варианта...
Решение из С -
void*плюс поле, указывающее тип того, на что указывает указатель (и только указатель - потому что разные типы могут иметь разные размеры, например...)Использовать для значения обертку - класс
any.
# include <string>
using std::string;
// этот класс не шаблон
// но потомки будут шаблонами
struct AttributeBase {
string name;
AttributeBase(string const & n);
// деструктор обязательно виртуальный
virtual ~ AttributeBase(){}
};
AttributeBase::AttributeBase(string const & n):
name{n}{}
struct BTree{
BTree * pLeft { } ;
BTree * pRight { } ;
// из-за неопределённого размера
// атрибуты могут быть только указателями
// тип указателя не шаблон,
// но на виртуальные шаблонные типы
AttributeBase * attr { } ;
BTree();
// для удаления атрибутов нужен деструктор
~ BTree();
void ChangeAttr(AttributeBase * at);
};
BTree::BTree(){}
BTree::~ BTree(){
// атрибут удаляется виртуально
delete attr;
}
void BTree::ChangeAttr(AttributeBase * at){
// атрибут удаляется виртуально
delete attr;
attr = at;
}
template <typename T>
struct Attribute : public AttributeBase
{
// аргументы передавать по значению это плохая практика
Attribute(string const & name,T const & value );
T value ;
virtual ~ Attribute();
};
template <typename T>
Attribute<T>::Attribute(string const & n,T const & v) :
AttributeBase{n},value{v}{
}
template <typename T>
Attribute<T> :: ~ Attribute(){}
struct XY{
int c[2];
} ;
int main(){
BTree bt ;
// в bt пустой артибут с указателем NULL
BTree btle ;
// атрибуты могут быть удалены, по-этому
// должны находиться в свободной памяти
Attribute<int> * ai = new Attribute<int>{"IntAttr",1};
btle.ChangeAttr(ai);
BTree btri ;
Attribute<string> * as = new Attribute<string>{"StrAttr","string"};
btri.ChangeAttr(as);
Attribute<XY> * ai2 =
new Attribute<XY>{"KoordAttr",{3,4}};
// удаляется старый атрибут, даём указатель на новый
btri.ChangeAttr(ai2);
}