Home > OS >  Compiler error on call to recursive function - "attempting to reference a deleted function"
Compiler error on call to recursive function - "attempting to reference a deleted function"

Time:12-02

I'm trying to write a binary tree to a file using a recursive function. The call to writeFile(std::string fileName) opens the file stream and then passes it to the recursive function call, writeFile(BinNode<T> ptr, std::ofstream outFile). The compiler comes back with the error "attempting to reference a deleted function" when the first function calls the second function (line noted in my code. I researched the error code and I have a default constructor, a destructor so none of the functions are implicit. Any ideas would be greatly appreciated.

BinTree.h:

#ifndef BINTREE_H
#define BINTREE_H

#include <iostream>
#include <fstream>
#include "BinNode.h"

template<typename T>
class BinTree {
public:
    BinTree(); // Default constructor
    // Value semantics
    // copy constructor
    BinTree(const BinTree<T>& source);
    // assignment operator
    BinTree<T>& operator=(const BinTree<T>& source);
    // destructor
    ~BinTree() { free(root); }

    bool isEmpty();
    void add(T item);
    void printAll() { print(root); }
    bool readFile(std::string fileName);
    bool writeFile(std::string fileName);

private:
    BinNode<T>* root;
    void free(BinNode<T>* ptr);
    void print(BinNode<T>* ptr);
    void copyTree(BinNode<T>* ptr);
    void writeFile(BinNode<T>* ptr, std::ofstream outFile);
};

#include "BinTree.template"
#endif

BinTree.template:

#include "BinTree.h"
// BinTree.template definition

template <typename T>
BinTree<T>::BinTree() {
    root = nullptr;
}

template<typename T>
BinTree<T>::BinTree(const BinTree<T>& source) {
    this->root = nullptr;
    copyTree(source->root);
}

template<typename T>
BinTree<T>& BinTree<T>::operator=(const BinTree<T>& source) {
    if (this == &source)
        return *this;
    free(this->root);
    this->root = nullptr;
    copyTree(source->root);
}

template<typename T>
bool BinTree<T>::isEmpty() {
    return (root == nullptr);  // true - empty, false - not empty
}

template<typename T>
void BinTree<T>::add(T item) {
    BinNode<T>* temp = new BinNode<T>(item);  // other constructor

    if (isEmpty())
        root = temp;
    else {
        BinNode<T>* ptr = root;
        while (ptr != nullptr) {
            if (temp->data <= ptr->data) {      // Left side
                if (ptr->left == nullptr) {     // Left spot open
                    ptr->left = temp;           // Add it
                    ptr = nullptr;              // End Loop
                }
                else {                          // Left spot not open
                    ptr = ptr->left;
                }
            }
            else {                              // Right side
                if (ptr->right == nullptr) {    // Right open
                    ptr->right = temp;          // Add it
                    ptr = nullptr;              // End Loop
                }
                else {
                    ptr = ptr->right;
                }
            }
        }
    }

}

template<typename T>
bool BinTree<T>::readFile(std::string fileName) {
    std::ifstream inFS;
    inFS.open(fileName);
    T temp;
    if (!inFS.is_open()) {
        std::cout << "Error opening " << fileName << std::endl;
        return false;
    }

    while (!inFS.eof()) {
        getline(inFS, temp);
        add(temp);
    }

    inFS.close();

    return true;
}

template<typename T>
bool BinTree<T>::writeFile(std::string fileName) {
    std::ofstream outFS;
    outFS.open(fileName);
    if (!outFS.is_open()) {
        std::cout << "Error writing to " << fileName << std::endl;
        return false;
    }

    writeFile(root, outFS);  // <------ COMPILER ERROR ON THIS LINE ****

    outFS.close();

    return true;
}

template<typename T>
void BinTree<T>::writeFile(BinNode<T>* ptr, std::ofstream outFile) {
    if (ptr != nullptr) {
        writeFile(ptr->left, outFile);
        outFile << ptr->data << std::endl;
        writeFile(ptr->right, outFile);
    }
}

template<typename T>
void BinTree<T>::free(BinNode<T>* ptr) {
    if (ptr != nullptr) {
        free(ptr->left);
        free(ptr->right);
        delete ptr;
    }
}

template<typename T>
void BinTree<T>::print(BinNode<T>* ptr) {
    if (ptr != nullptr) {
        print(ptr->left);
        std::cout << ptr->data << std::endl;
        print(ptr->right);
    }
}

template<typename T>
void BinTree<T>::copyTree(BinNode<T>* ptr) {
    if (ptr != nullptr) {
        add(ptr->data);
        copyTree(ptr->left);
        copyTree(ptr->right);
    }
}

BinNode.h:

#ifndef BINNODE_H
#define BINNODE_H

template <typename T>
class BinTree;

template <typename T>
class BinNode {
    friend class BinTree<T>;
public:
    BinNode() : left(nullptr), right(nullptr), data(T()) {} // Default constructor
    BinNode(T item) : left(nullptr), right(nullptr), data(item) {}

private:
    BinNode<T>* left;
    BinNode<T>* right;
    T data;

};

#endif

CodePudding user response:

Your function gets the std::ofstream by value, but the copy constructor is deleted: You need to pass the stream by reference instead:

template<typename T>
void BinTree<T>::writeFile(BinNode<T>* ptr, std::ofstream &outFile) {
    // ...
}
  • Related