5 Replies - 2277 Views - Last Post: 26 April 2010 - 12:27 PM Rate Topic: -----

#1 jaia  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 61
  • Joined: 21-March 10

"No matching function" error

Posted 25 April 2010 - 10:51 PM

I'm doing a problem that involves defining a Worker class and a QueueTp template class and testing them out with a simple program. Here's the program in question.

// workqueue.cpp -- Tests QueueTp template class

// compile with queuetp.cpp


#include <iostream>

#include "queuetp.h"


const int SIZE = 5;



int main() {

    using std::cin;

    using std::cout;

    using std::endl;
   

    QueueTp<Worker *> lolas(SIZE);

    Worker holder[SIZE];

    int ct;
    cout << "Enter data for " << SIZE << " workers.\n";
    for (ct = 0; ct < SIZE; ct++) {

        holder[ct].Set();
        cin.get();

    }
    
    for (int i = 0; i < ct; i++) 
	    lolas.enqueue(&holder[i]);



    cout << "\nYou have" << lolas.queuecount() << "workers. \n";

    for (int i = 0; i < ct; i++) {

        holder[i].Show();
        lolas.dequeue(&holder[i]);
    }
    cout << "You now have" << lolas.queuecount() << "workers. \n";
    

    cout << "Bye.\n";

    return 0; 

}




I'm getting the following error message from g++: "workqueue.cpp:30: error: no matching function for call to ‘QueueTp<Worker*>::dequeue(Worker*)’
queuetp.h:41: note: candidates are: bool QueueTp<Item>::dequeue(Item&) [with Item = Worker*]"

So it finds the correct function but then says it doesn't match! This apparently is connected with use or nonuse of const. The enqueue() method, which has the same signature but with a const argument, works fine. When I remove "const", it gives the same error that dequeue() does. Here are the two functions (directly from Prata):

// Add item to queue

template <typename Item>
bool QueueTp<Item>::enqueue(const Item & item) {

    if ( isfull() )

        return false;

    Node * add = new Node;  // create node

    if (add == NULL)

        return false;       // quit if none available

    add->item = item;       // set node pointers

    add->next = NULL;

    items++;

    if (front == NULL)      // if queue is empty,

        front = add;        // place item at front

    else

        rear->next = add;   // else place at rear

    rear = add;             // have rear point to new node

    return true;

}



// Place front item into item variable and remove from queue

template <typename Item>
bool QueueTp<Item>::dequeue(Item & item) {

    if (front == NULL)

        return false;

    item = front->item;     // set item to first item in queue

    items--;

    Node * temp = front;    // save location of first item

    front = front->next;    // reset front to next item

    delete temp;            // delete former first item

    if (items == 0)

        rear = NULL;

    return true;

}




And here's the header file:

//queuetp.h -- interface for a queue template class


#ifndef QUEUETP_H_

#define QUEUETP_H_


#include <string>

class Worker {
	private:
		std::string fullname;
		long id;
	public:
		Worker() : fullname("no one"), id(0L) { }
		Worker(const std::string & s, long n) : fullname(s), id(n) { }
		~Worker() { };
		void Set();
		void Show() const;
};

template <typename Item>

class QueueTp {

	private:

	    // Node is a nested structure definition local to this class

	    struct Node { Item item; struct Node * next;};

	    enum {Q_SIZE = 10};

	// private class members

	    Node * front;       // pointer to front of queue

	    Node * rear;        // pointer to rear of queue

	    int items;          // current number of items in queue

	    const int qsize;    // maximum number of items in queue

    // preemptive definitions to prevent public copying

 	   QueueTp(const QueueTp & q) : qsize(0) { }

 	   QueueTp & operator=(const QueueTp & q) { return *this;}

	public:

	    QueueTp(int qs = Q_SIZE); // create queue with a qs limit

	    ~QueueTp();

	    bool isempty() const;

	    bool isfull() const;

	    int queuecount() const;

	    bool enqueue(const Item &item); // add item to end

	    bool dequeue(Item &item);       // remove item from front

};


#endif




Thanks in advance!

Is This A Good Question/Topic? 0
  • +

Replies To: "No matching function" error

#2 sarmanu  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 966
  • View blog
  • Posts: 2,362
  • Joined: 04-December 09

Re: "No matching function" error

Posted 26 April 2010 - 05:24 AM

Well, you are using this:
QueueTp<Worker *> lolas(SIZE);


So, your "item" template type is a pointer to Worker. That means we can rewrite the member function dequeue, as this:
bool QueueTp<Worker *>::dequeue(Worker * &item) {
// function body
}


Uhh, that results in a pointer to reference. Is it what you want?
Not really! I suggest you to remove that '&' from the function parameter, so the function header becomes:
bool QueueTp<Worker *>::dequeue(Worker *item)
{
}



EDIT: Took a look at the struct, there's no need for the dereference of "item".

I hope this will help you clear the errors. If it doesn't, would you please post the entire code?

EDIT: since "enqueue" and "dequeue" are both boolean functions, why wouldn't you check their return value?
for (int i = 0; i < ct; i++) 
    // enqueue returns true/false. Check it's return value ...
    if (!lolas.enqueue(&holder[i]))
        handle_error_message;


Same goes for dequeue ...

This post has been edited by sarmanu: 26 April 2010 - 12:24 PM

Was This Post Helpful? 1
  • +
  • -

#3 jaia  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 61
  • Joined: 21-March 10

Re: "No matching function" error

Posted 26 April 2010 - 11:33 AM

Switching from reference arguments to regular arguments didn't help; it just gave me a bunch of "undefined reference" errors. Anyway, why does using const help? I can't use const for dequeue() because that method modifies its argument, but if I omit it from enqueue(), I get the same "no matching function" error that I do for dequeue().

Here are all the function definitions. They are taken verbatim or nearly so from Prata.

// queuetp.cpp -- QueueTp methods


#include <iostream>
#include "queuetp.h"


using std::cout;
using std::cin;

//Worker methods
void Worker::Set() {
	cout << "Enter worker's name: ";
	getline(cin, fullname);
	cout << "Enter worker's ID: ";
	cin >> id;
	while (cin.get() != '\n')
		continue;
}

void Worker::Show() const {
	cout << "Name: " << fullname << std::endl;
	cout << "Employee ID: " << id << std::endl;
}


//QueueTp methods

template <typename Item>
QueueTp<Item>::QueueTp(int qs) : qsize(qs) {

    front = rear = NULL;

    items = 0;

}



template <typename Item>
QueueTp<Item>::~QueueTp() {

    Node * temp;

    while (front != NULL)   // while queue is not yet empty

    {

        temp = front;       // save address of front item

        front = front->next;// reset pointer to next item

        delete temp;        // delete former front

    }

}



template <typename Item>
bool QueueTp<Item>::isempty() const {

    return items == 0;

}



template <typename Item>
bool QueueTp<Item>::isfull() const {

    return items == qsize;

}



template <typename Item>
int QueueTp<Item>::queuecount() const {

    return items;

}



// Add item to queue

template <typename Item>
bool QueueTp<Item>::enqueue(const Item & item) {

    if ( isfull() )

        return false;

    Node * add = new Node;  // create node

    if (add == NULL)

        return false;       // quit if none available

    add->item = item;       // set node pointers

    add->next = NULL;

    items++;

    if (front == NULL)      // if queue is empty,

        front = add;        // place item at front

    else

        rear->next = add;   // else place at rear

    rear = add;             // have rear point to new node

    return true;

}



// Place front item into item variable and remove from queue

template <typename Item>
bool QueueTp<Item>::dequeue(Item & item) {

    if (front == NULL)

        return false;

    item = front->item;     // set item to first item in queue

    items--;

    Node * temp = front;    // save location of first item

    front = front->next;    // reset front to next item

    delete temp;            // delete former first item

    if (items == 0)

        rear = NULL;

    return true;

}



Was This Post Helpful? 0
  • +
  • -

#4 sarmanu  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 966
  • View blog
  • Posts: 2,362
  • Joined: 04-December 09

Re: "No matching function" error

Posted 26 April 2010 - 12:07 PM

You were on the right track with removing that reference. You could compile. The undefined reference thingie was a linker error, not a compile error, and it occurred because you implemented templated functions in a separate file. You can't do that. Templated functions must be implemented in the same unit where they are prototyped.
Was This Post Helpful? 1
  • +
  • -

#5 jaia  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 61
  • Joined: 21-March 10

Re: "No matching function" error

Posted 26 April 2010 - 12:26 PM

That worked; thanks! BTW, the dequeue() function needed to use "item = front->item;", not "*item = front->item;" -- item is a pointer.

And if anyone can explain or point me to some references on how const comes into all of this, I'd greatly appreciate it.
Was This Post Helpful? 0
  • +
  • -

#6 sarmanu  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 966
  • View blog
  • Posts: 2,362
  • Joined: 04-December 09

Re: "No matching function" error

Posted 26 April 2010 - 12:27 PM

Two minutes ago I have edited my post. I didn't pay attention to that struct.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1