vector, узлы могут быть разного вида, N1 и N2, наследуются от Node, потом используются в Tree, в которой лежит корень дерева. Надо сделать контейнер для хранения потомков универсальным, чтобы можно было не только в vector хранить, а в list, deque или в собственном. Сейчас пытаюсь добавить в параметры Node для контейнера template<typename, typename...> class Container, typename... Params и потомков хранить в Container<std::shared_ptr<T<TIndex>>, Params...> children;. Но проблема с наследованием для N1 и N2. Подскажите, пожалуйста, как это правильно сделать, и как создавать объекты типа Tree с указанием контейнера для хранения узлов.
template <template <typename> class T, typename TIndex>
struct Node
{
TIndex index;
std::vector<std::shared_ptr<T<TIndex>>> children;
Node() : index(0) { }
};
template <typename TIndex>
struct N1: public Node<N1, TIndex>
{
N1() : Node<N1, TIndex>() {}
};
template <typename TIndex>
struct N2: public Node<N2, TIndex>
{
size_t count;
N2() : Node<N2, TIndex>(), count(0) {}
};
template <typename TNode> // можно N1 или N2 использовать
struct Tree
{
std::shared_ptr<TNode> root;
Tree()
{
root = std::make_shared<TNode>();
}
};
//Tree<N1<int>> obj; // или Tree<N2<int>>
//std::cout << obj.root->index << std::endl;
template<template <typename> class T, typename TIndex, template<typename, typename...> class Container, typename... Params>
struct NewNode
{
TIndex index;
Container<std::shared_ptr<T<TIndex>>, Params...> children;
NewNode() : index(0) { }
};
// а как создать NewN1 и NewN2 от NewNode а затем использовать при создании Tree?
Ты круто заморочился, респект
А это вообще реализуемо? Функцию, которая принимает любой контейнер ведь можно создать. Почему класс не создать
а у тебя в любой ноде может быть любой контейнер?
не, во всех одинаковый, только при создании дерева указывать какой контейнер использовать
аааа, не думал указывать аргументом шаблона?
Функцию, которая может принимать любой контейнер, не создать.
а как же так? template<template<typename, typename...> class Container, class T, typename... Params> void f(Container<T, Params...> const& u) { std::cout << u.size() << std::endl; } int main() { std::vector<int> a(10, 1); std::list<int> b(10, 1); f(a); f(b); }
Вообще, узлам дерева не нужно быть разного типа. Содержимому узлов -- можно. А самим узлам - нет смысла, вроде бы. Ну или я что-то не понимаю
я ведь могу в аргументы передать любого вида контейнер?
тут идея такая, хранить список узлов в контейнере который определишь сам при создании дерева.
Русский родной? Я не понимаю
да, сорян, исправил)
В функцию - не можешь
в шаблон функции могу?
А работать как с ними? С set как с vector?
через итераторы планировал
В шаблон - можешь
Не все так просто. Меерса читал?
хотел переехать с vector на свой контейнер, но не хотел портить весь остальной функционал, работа внутри в основном через стандартные stl алгоритмы
нет)) в какой из книг, подскажите
ну так в чем проблема, у тебя же уже есть template <typename> class T таким же параметром добавь контейнер
Вообще, ты делаешь дерево. Зачем все узлы хранить в одном контейнере? Я не очень понимаю.
В первой. Хотя, может в той что про STL. Глава называется "остерегайтесь писать контейнеро-независимый код"
вот сейчас пытаюсь, да)
во, спасибо, гляну, походу это как раз выстрел в ногу у меня
так их много, не два, нужен контейнер
Короче не делай так. В принципе есть разные контейнеры это - массивы - списки - словари Они в работе принципиально разные.
Зачем? В каком месте дерева, общения с ним, нужен общий контейнер, хранящий все узлы в одном месте?
а где там узлы в одном месте то? Там в контейнере вроде sptr на ноду (рут), а каждая нода хранит как раз N нод, т.к. просто дерево в общем случае, не бинарное
Понял, я почитаю. С контейнерами знаком, и сложность при работе с итераторами там разная, просто не хотел менять везде vector, а указать как параметром
По сути дерево - это двумерный список. В списке все узлы не хранятся в одном контейнере. Почему в дереве должны?
Так я не знаю, вот человек такое писать хочет...
ну в его самом первом примере вроде всё ок было )
я понимаю, что ты хочешь сказать, но нет
Да, в общем виде: узел->массив потомков такого же типа
не понял)) можно оптимальнее хранить дерево общего вида?
Ну вот он... Я лично слабо понимаю зачем это все.
Ну, скажи мне...
общего вида вроде нет
Ты пишешь дерево, так? И хочешь все узлы дерева помимо хранения в дереве также хранить ещё и в каком-то контейнере, так?
ну двумерный список это все-таки плоская сетка
нее, я просто хотел при создании дерева указать в каком из контейнеров должен храниться список дочерних узлов
ладно, господа, походу главный вопрос был действительно не в том как это сделать, а зачем, о котором я не подумал) уже сильно сомневаться начал)) спасибо за ваше время
А, понял. Там надо либо вектор, либо список, либо просто что-то своё, если узлы разного типа, наверное просто сделать динамический массив указателей
Тут есть такая большая тонкость с ковариантностями за косвенностью, Base** не связано с Derived**, пока не довешан const. В случае с деревом это примерно означает, что полиморфный узел дерева может только разрешать перечислить потомков, но не может напрямую давать их изменять. Пример на подумать void f(Derived** ppderived) { Base** ppbase = reinterpret_cast<Base**>(ppderived); //C++ понимает эту тонкость и запрещает такие неявные касты *ppbase = new Base(); //*ppderived теперь не Derived }
Обсуждают сегодня