Получение ошибки из-за шаблона в классе Tree - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть класс Tree , и в этом классе у меня есть класс Node (вложенный), который является приватным. Класс Tree , конечно же, является шаблоном класса.
Проблема в том, что когда я хочу вставить дочерний элемент дерева в родительский элемент дерева, у которого нет точного числа дочерних элементов, я получаю сообщение об ошибке:совместимый тип для преобразования.


Вот мой код:
tree.hpp

#ifndef TREE_HPP
#define TREE_HPP

#include <iostream>
#include <cstddef> 

template <typename T, char N>
class Tree {
private:
  class Node;
  Node* _info;
public:
  Tree();
  Tree(T, char);
  Tree(const Tree&) = delete;  // copy constructor
  Tree& operator= (const Tree&) = delete; // assignement by copy constructor
  Tree (Tree&&); // transfer constructor
  Tree& operator= (Tree&&); // assignement by transfer constructor
  ~Tree() {delete _info;}
  bool ins(char, Tree&);
  Tree* fils(char);
};

template <typename T, char N>
Tree<T, N>::Tree() 
  : _info(nullptr) {}

template <typename T, char N>
Tree<T, N>::Tree(T data, char size) {
  Node* node = new Node(data);
  _info = node;
}

template <typename T, char N>
Tree<T, N>::Tree(Tree&& t) {
  _info = t._info;
  t._info = nullptr;
}

template <typename T, char N>
Tree<T, N>& Tree<T, N>::operator= (Tree&& t) {
  if (&t != this) {delete _info; _info = t._info; t._info = nullptr;}
  return *this;
}

template <typename T, char N>
bool Tree<T, N>::ins(char index, Tree& childTree){
  if (_info){
    _info->getChildren()[index] = &childTree;
    return true;
  }
  return false;
}

template <typename T, char N>
Tree<T,N>* Tree<T, N>::fils(char index){
  return _info->getChildren()[index];
}

template <typename T, char N>
class Tree<T, N>::Node {
private:
  T _data;
  Tree* _children[N];
  bool _isWord;
public:
  Node();
  Node(T);
  Tree** getChildren() {return this->_children;}
  T getData(){return this->_data;}
  ~Node() = default;
};

template <typename T, char N> // Node class default constructor
Tree<T,N>::Node::Node(){
  _data = 0;
  _children = nullptr;
  _isWord = false;
}

template <typename T, char N> // Node class constructor
Tree<T,N>::Node::Node(T data){
  _data = data;
  _isWord = false;
  for (char i = 0; i < N; i++) 
    _children[i] = NULL;
}

#endif

main.cpp

#include <iostream>
#include <cstddef>
#include "tree.hpp"

#define SIZE 5
#define display(x) std::cout<<x<<std::endl
int main() {
  Tree<char,SIZE> n1('A',SIZE);
  Tree<char,SIZE> n1_1('B',SIZE); // works fine
  Tree<char,10> n1_2('C',10); // sends the error
  n1.ins(0,n1_1);
  n1.ins(1,n1_2);
  return 0;
}

и ошибка:

main.cpp: In function ‘int main()’:
main.cpp:16:12: error: cannot convert ‘Tree<char, '\012'>’ to ‘Tree<char, '\005'>&’
   16 |   n1.ins(1,n1_2);
      |            ^~~~
      |            |
      |            Tree<char, '\012'>
In file included from main.cpp:4:
tree.hpp:80:40: note:   initializing argument 2 of ‘bool Tree<T, N>::ins(char, Tree<T, N>&) [with T = char; char N = '\005']’
   80 | bool Tree<T, N>::ins(char index, Tree& childTree){
      | 

Я также открыт для предложений о способах улучшения этого кода.
Спасибо ...

Ответы [ 3 ]

1 голос
/ 07 ноября 2019

Класс Tree - это, конечно, шаблонный класс.

Дерево не обязательно является шаблоном. Не делайте вещи «только потому, что»;).

Tree<char,10> и Tree<char,5> - это два разных типа. Вы не можете преобразовать одно в другое, если вы не реализуете некоторые средства для их преобразования.

Непонятно, почему вы решили, чтобы количество дочерних узлов в дереве было частью типа деревьев. Добавление или удаление потомков даст вам другой тип дерева.

Рассмотрим std::array против std::vector. std::array имеет количество элементов в качестве параметра шаблона, потому что его размер никогда не может измениться. С другой стороны, std::vector имеет динамический размер.

На самом деле я не понимаю, почему ваш Tree должен знать о размере его узлов children массива. Либо я пропустил это, либо вы никогда не используете N в Tree. Я не следовал всем деталям, но, кажется, вы можете безопасно удалить N из своего кода и использовать std::vector для дочерних узлов.

0 голосов
/ 07 ноября 2019

Когда c ++ создает объект, он создает его статически, что означает, что объект с размером 4 является целым объектом, отличным от объекта с размером 5. Эти два объекта не похожи друг на друга, и вы не можете отследить их, как если бы они были * 1001. *

0 голосов
/ 06 ноября 2019

Почему бы вам не использовать std :: vector и только передать N в качестве параметра узлу? Затем вы создаете функцию вставки в узле, которая проверяет, что максимальный размер не достигнут

...