0

So, i'm attempting to implement this Queue using my LinkedList that I previously created. I've provided the code for both classes. Currently, I'm work on attempting to get pop and push to work without changing the function prototype (it's for an assignment).

When looking specifically at peek(I haven't quite finished pop), for some reason, when I run the code, I get strange pointer error.

Error C2440 'default argument': cannot convert from 'int' to 'int &'

I'm not sure exactly what that means in this context. The function is suppose to look at the object at the top of the queue without removing it, and return true or false based upon if the operation was successful or not.

Here is the info for QUEUE.

  #ifndef _QUEUE_H
#define _QUEUE_H 1

#include "QueueInterface.h"
#include "LinkedList.hpp"

template <typename T>
class Queue : public QueueInterface<T>
{
protected:
    LinkedList<T> _list;
    int count;

public:

    unsigned size() const
    {
        return count;
    }

    bool push(const T& val = T{})
    {
        _list.push(val);
        count++;
        return true;
    }

    bool empty() const
    {
        return _list.isEmpty();
    }

    bool pop(T& val = T{})
    {
        return true;
    }

    bool peek(T& val = T{}) const
    {
        std::cout << _list.last() << std::endl;
        return true;

    }

    void clear()
    {
        _list.clear();
    }

    int search(const T& target = T{}) const
    {
        return _list.search(target);
    }
    //
    // Internal consistency check
    //

    void toString()
    {
        _list.toString();
    }

public:
    virtual bool check() const
    {
        return _list.check();
    }
};

#endif

Here is Linked List.

#ifndef _LINKED_LIST_GUARD
#define _LINKED_LIST_GUARD 1

#include <iostream>

#include "ListInterface.h"

template <typename T>
class LinkedList : public ListInterface<T>
{
public:

    int count = 0;


    LinkedList()
    {
        _head = new Node;
        _tail = new Node;

        _head->_next = _tail;
    }


private:

    //
    // Private node class to facilitate linked list
    //
    class Node
    {
    public:
        T _data;
        Node* _next;

        // Constructor: default
        Node(T d = T{}, Node* n = nullptr) : _data(d), _next(n) {}

        ~Node() { _next = nullptr; }
    };

    //
    // Prevent copying and assigning
    //
    LinkedList(const LinkedList& rhs) {}
    const LinkedList& operator=(const LinkedList& rhs) {}

public:
    //
    // LinkedList instance variables; we use dummy head and tail nodes in this implementation

    unsigned _size;
    Node* _head;
    Node* _tail;

    // Returns the first element in the list
    T& first() const
    {
        return _head->_next->_data;
    }

    // Adds an item to the LEFT side of the linked list
    void push(const T& x)
    {
        // Creates a new node with the user input data.
            Node* current = new Node;
            current->_data = x;

            current->_next = _head->_next;
            _head->_next = current;

            count++;


    }

    // ASK ABOUT
    T& operator[](unsigned n)
    {
        int position = 1;

        if (n != count)
        {
            throw("Invalid Position");
        }

        for (Node* current = _head->_next; current != _tail; current = current->_next, position++)
        {
            if (position == n)
            {
                return current -> _data;
            }
        }


    }


    void clear()
    {
        do
        {
            pop();
        } while (count != 0);

    }

    bool contains(const T& target) const
    {
        for (Node* current = _head->_next; current != _tail; current = current->_next)
        {
            if (current->_data == target)
                return true;
        }
        return false;
    }

    bool pop()
    {
        if (_head->_next == _tail)
        {
            std::cout << "unable to pop, list is empty";
            return false;
        }

        if (_head->_next != _tail)
        {
            Node* deleteNode = _head->_next;
            _head->_next = _head->_next->_next;
            delete deleteNode;
            count--;
            return true;
        }
        return false;
    }

    T& last() const
    {
        if (_head->_next == _tail)
        {
            std::cout << "LIST IS EMPTY" << std::endl;
        }

        if (_head->_next != _tail)
        {
            for (Node* current = _head->_next; current != _tail; current = current->_next)
            {
                if (current->_next == _tail)
                    return current->_data;
            }
        }
    }

    // ASK ABOUT
    int search(const T& target = T{}) const
    {
        int position = 1;
        for (Node* current = _head->_next; current != _tail; current = current->_next)
        {
            if (current->_data == target)
            {
                return position;
            }
            else  position++;
        }
        return -1;

    }

    bool isEmpty() const
    {
        if (_head->_next == _tail)
        {
            return true;
        }
        return false;
    }

    unsigned size() const 
    {

        return count;
    }


    bool remove(const T& target)
    {
        Node* deleteNode = nullptr;
        Node* trailer = _head;
        Node* current = _head->_next;

        while (current != _tail && current-> _data != target)
        {
            trailer = current;
            current = current->_next; 
        }

        if (current->_data == target)
        {
            deleteNode = current;
            current = current->_next;
            trailer->_next = current;

            delete deleteNode;
            count--;
            return true;
        }
        else
            std::cout << "unable to remove, item not in list" << std::endl;
        return false;

    }

    //FOR TESTING
    void toString()
    {
        for (Node* current = _head->_next; current != _tail; current = current->_next)
        {
            std::cout << current->_data << std::endl;
        }
    }

    //
    // Internal consistency check
    //
public:
    virtual bool check() const
    {
        bool sizeConsistent = isSizeConsistent();
        bool headTailConsistent = isEndConsistent();

        if (!sizeConsistent) std::cerr << "Size inconsistent" << std::endl;
        if (!headTailConsistent) std::cerr << "Head / Tail inconsistent" << std::endl;

        return sizeConsistent && headTailConsistent;
    }

    //
    // Stated size is accurate to the entire list
    //
    bool isSizeConsistent() const
    {
        int count = 0;
        for (Node* current = _head->_next; current != _tail; current = current->_next)
        {
            count++;
        }

        return size() == count;
    }

    //
    // Checks that the head and tail are defaulted properly and the
    // respective next pointers are appropriate.
    //
    bool isEndConsistent() const
    {
        if (_head->_data != T{}) return false;

        if (_tail->_data != T{}) return false;

        if (_head->_next == nullptr) return false;

        if (_tail->_next != nullptr) return false;

        if (isEmpty() && _head->_next != _tail) return false;

        if (!isEmpty() && _head->_next == _tail) return false;

        return true;
    }
};

#endif

And finally, here is my main. The top portion is to test the functionality for LinkedList. The bottom portion is what I was working with to test queue.

#include "Queue.hpp"
#include "LinkedList.hpp"
#include <string>
#include <iostream>


int main()
{
    LinkedList<int> list;
    LinkedList<int> listEmpty;
    Queue<int> list2;

    list.push(1);
    list.push(2);
    list.push(3);
    list.push(4);
    list.push(5);



    list.remove(1);

    std::cout << "List contains 4? " << list.contains(4) << std::endl;
    std::cout << "List empty? " << list.isEmpty() << std::endl;
    std::cout << "List size: " << list.size() << std::endl;
    std::cout << "Last in list? " << list.last() << std::endl;
    std::cout << "What is in position 4? " << list[4] << std::endl;
    std::cout << "Search " << list.search(10) << std::endl;
    //std::cout << "3 is in position " << list.search() << std::endl;
    std::cout << " " << std::endl;




    list.toString();
    list.clear();
    std::cout << "///////////////////////////////////////////////////////////////////////////////" << std::endl;
    list.push(4);

    list.toString();
    std::cout << "///////////////////////////////////////////////////////////////////////////////" << std::endl;
    std::cout << "QUEUE STUFF" << std::endl;
    std::cout << "///////////////////////////////////////////////////////////////////////////////" << std::endl;

    list2.push(1);
    list2.push(2);
    list2.push(6);
    list2.push(3);
    list2.push(4);
    list2.push(5);

    std::cout << "Queue empty? " << list2.empty() << std::endl;
    std::cout << "Queue size: " << list2.size() << std::endl;

    std::cout << "First in Queue? " << list2.peek() << std::endl;
    std::cout << "What position is 6 in? : " << list2.search(6) << std::endl;

    list2.toString();



    std::cout << " " << std::endl;

    system("pause");

I guess my question is this, what steps can I take to go about fixing this particular function?

Thanks in advance!

Granzo
  • 59
  • 1
  • 7
  • where is your main.cpp? – iamnoten Nov 14 '17 at 08:26
  • The default parameter in function members is mandatory? Why do you need push a default T?? – JTejedor Nov 14 '17 at 08:31
  • @iamnoten Posted! – Granzo Nov 14 '17 at 08:49
  • @JTejedor Well, according to my professor, he wants us to be able to push any data type. So i'm not exactly sure. Sorry. – Granzo Nov 14 '17 at 08:50
  • It is very different that a queue can push any data type from a queue push a default value. Think about it, for example, with int type, any time that you use push with empty parameter, the default int (any value, depends of compiler) is inserted in your queue. So maybe, you should change your function member with no default parameter. – JTejedor Nov 14 '17 at 08:55
  • Your code is broken in many places, turn on your warning and *read* them. Also, learn to make a [mcve], your problem is clearly in the single function `peek` – Passer By Nov 14 '17 at 09:43

1 Answers1

0

The problem with your code is that peek, as you said, should not modify the Queue and neither take any parameter because it merely looks at the top of the structure and returns either true or false.

So a solution is to remove the parameter in peak as follows and everything compiles and runs.

bool peek() const
{
    std::cout << _list.last() << std::endl;
    return true;

}

Specifically, the error you get is because you cannot assign to a non-const lvalue reference an rvalue reference. This is exactly what you are doing in T& val = T{}. T{} is an rvalue and clearly, val is a non-const reference to T.

You can try using bool peek(const T& val = T{}) const and see by yourself that everything compiles fine.

Davide Spataro
  • 7,319
  • 1
  • 24
  • 36