I'm having a problem with return value/reference. I'm writing a template (queue), and Front() function is supposed to return the element from the front of the queue, but I get an error -- No viable conversion from 'Queue<int>::Node' to 'const int'. When I remove const, I get Non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'Queue<int>::Node' instead, and other variations of reference/no reference, const/no const give me either of the two errors. What am I missing?
#include <iostream>
using namespace std;
template <typename T>
class Queue
{
friend ostream& operator<< (ostream &, const Queue<T> & );
private:
class Node
{
friend class Queue<T>;
public:
Node(const T &t): node(t) {next = 0;}
private:
T front;
T back;
T node;
Node *next;
};
Node *front;
Node *back;
public:
Queue() : front(0), back(0) {}
~Queue();
bool Empty()
{
return front == 0;
}
T& Front()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
T const & temp = *front; // error here
return temp;
}
}
/* ... */
};
template <class T> ostream& operator<< (ostream &, const Queue<T> & );
int main()
{
Queue<int> *queueInt = new Queue<int>;
for (int i = 0; i<10; i++)
{
queueInt->Push(i);
cout << "Pushed " << i << endl;
}
if (!queueInt->Empty())
{
queueInt->Pop();
cout << "Pop" << endl;
}
queueInt->Front();
return 0;
}
Your Node class definition doesn't make much sense: the way it's now, each node stores 3 data values: front, back and node. Is the class supposed to be a queue of triples?
Nevertheless, in your Front() function, you to need to return the "payload" of the front node (i.e. return something of type T), not the node itself. Something like this:
T& Front()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
return front->node;
}
}
Replace
T const & temp = *front;
with
T& temp = front->front;
Queue<T>::front is a pointer to a Node, in other words, *front is a Node. You are trying then to assign a Node to a T& const and, since the compiler cannot convert from Node to T it complains. Now, the Node has a member also called front which is T and I suppose that's what you want to return and that's what the fix does. (Possibly you want to return front->node. Your intent is not clear to me.)
In addition, you declared temp as T const & and Front returns it. However, the type returned by Front is T& (non nonst) and the compiler cannot convert from const to non-const. By declaring temp non-const (as in the fix) such conversion is no longer required.
Related
So I'm trying to overload the ^ operator to perform the intersection between my two sets, but I keep getting this compile time error "Invalid operands to binary expression.
intersection = list ^ listTwo; is what causes the error
My methods work fine without overloading.
Here is my header file.
#ifndef SetHeader_h
#define SetHeader_h
template<typename T>
class Node{
public:
T data;
Node<T> *next;
};
template<typename T>
class SetADT{
private:
Node<T> *head;
public:
SetADT();
~SetADT();
void add(T data);
void print();
bool isDuplicate(T data) const;
SetADT<T> operator ^ (SetADT<T> node);
};
#endif /* SetHeader_h */
Here is my cpp file
#include <iostream>
#include "SetHeader.h"
using namespace std;
template <typename T>
SetADT<T> ::SetADT(){
head = NULL;
}
template<typename T>
SetADT<T> :: ~SetADT<T>(){
cout<<"Set deleted!" << endl;
}
template<typename T>
bool SetADT<T>::isDuplicate(T data) const{
Node<T> *cur = this->head;
while (cur) {
if (cur->data == data) {
return true;
}
cur=cur->next;
}
return false;
}
template <typename T>
void SetADT<T>:: add(T data){
Node<T> *node = new Node<T>();
bool isPresent = isDuplicate(data);
if (!isPresent) {
node->data = data;
node->next = this->head;
this->head = node;
}
}
template <typename T>
void SetADT<T>:: print(){
Node<T> *head = this->head;
if (head == NULL) {
cout << "{}";
}
Node<T> *cur = head;
while (cur) {
cout << cur->data << ' ';
cur = cur->next;
}
cout << endl;
}
template <typename T>
SetADT<T> SetADT<T> :: operator &(SetADT<T> one){
SetADT<T> result;
Node<T> *setACurrent = this->head;
while (setACurrent) {
if (one.isDuplicate(setACurrent->data)) {
result.add(setACurrent->data);
}
setACurrent = setACurrent->next;
}
return result;
}
int main (){
SetADT<int> list;
list.add(10);
list.print();
SetADT<int> listTwo;
listTwo.add(10);
list.print();
SetADT<int> intersection;
//error right here
intersection = list ^ listTwo;
return 0;
}
The essence of your problem is that the operator function is defined for the class SetADT<T>, however you are are trying to invoke the ^ operator against pointers (to objects); the compiler does not match your operator function implementation to your usage. Only the bitwise-xor (^) operator is defined and it does not know how to handle SetADT<T> arguments.
In order for the complier to match the invocation with your declaration, you need to dereference the left-hand "argument," list.
intersection = *list ^ listTwo;
I might suggest that you write the operator to accept reference arguments rather than pointers, like so:
SetADT<T>* operator ^ (SetADT<T> &node) { … }
Then you invoke it,
intersection = *list ^ *listTwo;
Of course you can leave the existing declaration/definition in place if there is a reason for it, but it is not nice. You should consider returning a reference to the object rather than a pointer. And, for completeness, you should consider implementing the ^= operator, as well.
SetADT<T>& operator ^ (SetADT<T> &node);
SetADT<T>& operator ^=(const X& rhs);
Then the expression to use for ^ operator could look like,
*intersection = *list ^ *listTwo;
list ^ listTwo;
Both list and listTwo are a SetADT<int> *, a pointer to an instance of this template. Both operands of this ^ operator are pointers.
template<typename T>
class SetADT{
// ...
SetADT<T>* operator ^ (SetADT<T> *node);
Here you defined the ^ operator of a SetADT<T>, and not a SetADT<T> *.
This operator^ declaration ends up overloading an operator on an instance of the class, and not on a pointer to the instance of the class.
That's how operator members work: they overload an operator on an instance of the class, and not on a pointer to an instance of the class.
If you would like to invoke this operator correctly, the right syntax would be:
(*list) ^ listTwo
Here, *list dereferences a pointer to an instance of a class, so you end up with (a reference to) an instance of the class, which has an operator^ overload that takes a pointer to an instance of the same class as a parameter.
Note that your operator overload's parameter is a pointer to an instance of the class, and since listTwo is such a pointer, this should work.
The general mistake you are making is that you are not correctly understanding the fundamental difference between a class and a pointer to an instance of the class. The is not a trivial matter, it's an important distinction. If something is defined to work for an instance of a class, it expects to have an instance of a class to work with, and not a pointer of such a class. And vice-versa.
I am creating a class LinkedList. I am having difficulty adding another node to my list.
Here is what I have so far:
template<typename T>
class LinkedList
{
private:
T element;
T *next;
public:
LinkedList();
LinkedList(T element);
void add(LinkedList<T> &otherList);
void print();
};
template<typename T>
LinkedList<T>::LinkedList()
{
next = NULL;
}
template<typename T>
LinkedList<T>::LinkedList(T element)
{
this->element = element;
next = NULL;
}
template<typename T>
void LinkedList<T>::add(LinkedList<T> &otherList)
{
next = &otherList;
}
template<typename T>
void LinkedList<T>::print()
{
LinkedList<T> *current = this;
while (current != NULL)
{
std::cout << current->element;
current = current->next;
}
}
int main()
{
LinkedList<std::string> myFirst("First");
LinkedList<std::string> mySecond("Second");
myFirst.add(mySecond);
myFirst.print();
return 0;
}
This works however if I make the change:
void add(const LinkedList<T> &otherList);
template<typename T>
void LinkedList<T>::add(const LinkedList<T> &otherList)
{
next = &otherList; //now an error right here
}
Then I get an error stating:
Assigning to 'LinkedList<std::__1::basic_string<char> > *' from incompatible type 'const LinkedList<std::__1::basic_string<char> > *'
Why is it I get this error?
next is a T*, and you're trying to assign a const LinkedList<T>* to it.
I suppose you meant something like next = &(otherList.element) (though even then I think your list semantics are somewhat broken — elements shouldn't typically be shared by multiple containers unless you're very, very clear about the ownership semantics).
Contrary to your claims, your first program doesn't work either for the same reason.
Here's a template (queue) I'm trying to write:
#include <iostream>
using namespace std;
template <typename T>
class Queue
{
friend ostream& operator<< (ostream &, const Queue<T> & );
private:
template<class> class Node;
Node<T> *front;
Node<T> *back;
public:
Queue() : front(0), back(0) {}
~Queue();
bool Empty()
{
return front == 0;
}
void Push(const T& NewEl)
{
Node<T&> *El = new Node<T> (NewEl);
if (Empty())
front=back=El;
else
{
back-> next = El;
back = El;
}
}
void Pop()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
Node<T> *El = front;
front = front -> next;
delete El;
}
}
void Clear()
{
while (! Empty())
Pop();
}
};
template <typename T>
class Node
{
friend class Queue<T>;
public:
Node() {next = 0;}
Node(T nd) {nd=node; next=0;}
T& getsetnode(){return node;}
Node<T>*& getsetnext(){return next;}
private:
T front;
T back;
T node;
Node<T> *next;
};
template <class T> ostream& operator<< (ostream &, const Queue<T> & );
int main()
{
Queue<int> *queueInt = new Queue<int>;
for (int i = 0; i<10; i++)
{
queueInt->Push(i);
cout << "Pushed " << i << endl;
}
if (!queueInt->Empty())
{
queueInt->Pop();
cout << "Pop" << endl;
}
queueInt->Front();
queueInt->Back();
queueInt->Clear();
cout << "Clear" << endl;
return 0;
}
At these lines:
Node<T&> *El = new Node<T> (NewEl);
front = front -> next;
delete El;
I get Implicit instantiation of undefined template 'Queue<int>::Node<int>'. What am I doing wrong? After reading this post I tried changing int to const int to see if that was the problem, but apparently it isn't, because I get the same error.
I'm using XCode with LLVM compiler 4.2. When I switch to GCC I get more errors:
template<class> class Node; gets Declaration of 'struct Queue<int>::Node<int>',
Node<T&> *El = new Node<T> (NewEl); gets Invalid use of incomplete type,
and anything dealing with assignment of anything to El can't convert <int&>* to <int>* (but deleting reference doesn't change anything for LLVM).
template <typename T>
class Queue
{
private:
template<class> class Node;
/* ... */
This is a forward declaration of Queue::Node. The latter defined class Node is in the global namespace, so they aren't the same and any usage of Queue::Node will result in an incomplete-type error. Since you don't provide an interface to the interior nodes anyway just scrap the global definition of Node and stick it into Queue:
template <typename T>
class Queue
{
private:
class Node
{
public:
Node() {next = 0;}
/* ... */
};
/* ... */
};
I have made a template class for a node in a linked list and I'm trying to have it output its contents to an output stream by overloading <<. However my current code:
#include <iostream>
using namespace std;
template<class NType> class Node;
template<class NType>
class Node {
private:
void deletePointer(NType* p);
public:
NType data;
Node *prev, *next;
template<typename T>
struct is_pointer { static const bool value = false; };
template<typename T>
struct is_pointer<T*> { static const bool value = true; };
Node();
Node(NType data);
~Node();
};
int main() {
Node<int> *n1 = new Node<int>();
Node<int> *n2 = new Node<int>(10);
std::cout << "Node 1: " << n1 << std::endl;
std::cout << "Node 2: " << n2 << std::endl;
}
template<class NType> inline std::ostream & operator << (std::ostream& out, const Node<NType> &node){
out << node.data;
return out;
}
template<class NType> inline Node<NType>::Node()
:data(NULL), prev(NULL), next(NULL)
{
}
template<class NType> inline Node<NType>::Node(NType data)
:data(data), prev(NULL), next(NULL)
{
}
template<class NType> inline Node<NType>::~Node(){
if(is_pointer<NType>::value){
deletePointer(&data);
} else {
return;
}
}
template<class NType> inline void Node<NType>::deletePointer(NType* p){
delete p;
}
Outputs memory locations rather than the data within the nodes. This happens with primitive types such as int and the like as if it didn't know what kind of data was in the NType container.
Node 1: 0x741010
Node 2: 0x741030
Node 3: 0x741070
Node 4: 0x741090
I've tried using typename rather than class but still no dice... Is there any way to dynamically find out what type the template is using and cast or something prior to insertion? I know I can make a ton of redundant code for all the primitives but that seems wasteful and unnecessary.
If it helps any, I'm compiling on Arch Linux x64 with GCC v4.6.2 20111223
Edit: Since a lot of people are mentioning it. I've also tried putting the class outside as a friend and as a stand alone function neither of which work because the stream outputs address rather than the data itself regardless of where I put it. There are no private data values to be accessed so it's OK for it to not be a friend.
Edit:
Test case: http://ideone.com/a99u5
Also updated source above.
Edit:
Added the remaining portion of my code to assist Aaron in his understanding of the code.
Your code declares the operator<< as a member function, so it would actually take the this pointer as first argument and ostream as second. Instead it needs to be a free function:
template<class NType> class Node {
public:
NType data;
Node *prev, *next;
};
//Note how this is declared outside of the class body, so it is a free function instead of a memberfunction
template<class NType> inline std::ostream& operator<<(std::ostream& out, const Node<NType>& val){
out << val.data;
return out;
}
however if your operator<< needs access to private data you need to declare it as a friend function instead:
template<class NType> class Node {
public:
NType data;
Node *prev, *next;
friend std::ostream& operator<<(std::ostream& out, const Node& val){
out << val.data;
return out;
}
};
Now for your output: If your operator<< was invoked the compiler would know the type of NType and do the right thing when streaming the data member. However since your operator<< should not have worked (as written) and it seems to give you memoryaddresses as output I would assume you have something like the following:
Node* n = new Node();
std::cout<<n;
//When it should be:
std::cout<<*n;
Now just for curiosity sake: Why are you implementing what looks curiously like a linked list yourself instead of simply using std::list?
Edit:
Now that we can see the testcase it seems the assumptions about how the operator<< was called was correct. The output needs to be changed to:
std::cout << "Node 1: " << *n1 << std::endl;
std::cout << "Node 2: " << *n2 << std::endl;
to actually invoke the operator<< for Node, instead of the generic one for T*
Why are you adding a template<class NType> in front of your already templated class method?
Generally, the best way of overloading operator<< is to make it a friend:
template<typename NType>
friend std::ostream& operator<<(std::ostream& out, const Node<NType>& node)
{
out << node.data;
return out;
}
Edit: To respond to the comment below, this is what I mean:
When you define a class template in the header, you don't redeclare that template for the member functions of the class:
template<typename T>
class Foo
{
T some_data;
void member_fn();
}
This is required when you're declaring a non-member friend function, however:
template<typename NType>
class Node
{
public:
NType data;
Node<NType> *prev, *next;
//Note the different template parameter!
template<typename NType1>
friend std::ostream& operator<<(std::ostream& out, const Node<NType1>& node);
};
Implementation of that then becomes the above template<typename NType> std::ostream& operator<<(std::ostream& out, const Node<NType>& node) implementation.
template <class NType>
class Node
{
public:
NType data;
Node *prev, *next;
};
template <class NType>
inline std::ostream& operator<<(std::ostream& os, const Node<NType>& n)
{
return out << n.data;
}
You're printing the node addresses, not the nodes:
int main() {
Node<int> *n1 = new Node<int>();
Node<int> *n2 = new Node<int>(10);
std::cout << "Node 1: " << n1 << std::endl;
std::cout << "Node 2: " << n2 << std::endl;
}
n1 and n2 are pointers, not objects. You should have written:
int main() {
Node<int> *n1 = new Node<int>();
Node<int> *n2 = new Node<int>(10);
std::cout << "Node 1: " << *n1 << std::endl;
std::cout << "Node 2: " << *n2 << std::endl;
}
or:
int main() {
Node<int> n1();
Node<int> n2(10);
std::cout << "Node 1: " << n1 << std::endl;
std::cout << "Node 2: " << n2 << std::endl;
}
Others have pointed out that you need to use cout << *n1 instead of cout << n1, but there is another important bug in your code.
Your destructor includes a call deletePointer(&data); where data is a member of the class. This is dangerous. If this line of code ever was executed, then the program would probably crash. data is just one small part of the object pointed at by this, trying to delete it is like trying to delete a single element in an array is ints.
Node<int> *n1 = new Node<int>();
delete n1; // this makes sense. deleting the same thing that was new'ed
Node<int> *n1 = new Node<int>();
delete &(n1->data); // BUG
You should probably change your design a lot and simply remove the special code for pointer. Do you expect to write code like: Node<int*> *n2 = new Node<int*>( new int ); ? And if so, how do you want it to behave?
If NType actually was a pointer type, like int*, then it might make sense to do deletePointer(data), but it'll never make sense to do deletePointer(&data).
I have the following main.cpp file
#include "listtemplate.h"
//#include <iostream>
using namespace std;
int main()
{
int UserChoice;
cout << "Hello, World!" << endl;
cin >> UserChoice;
cout << UserChoice;
}
In it's current form, everything works. I enter an integer, and that integer is printed to the screen. However, when I uncomment the cout << "Hello, World!" << endl line, I get the following error
main.cpp:10: error: ambiguous overload for ‘operator<<’ in ‘std::cout << "Hello, World!"’
I can also make it work by commenting out #include "listtemplate.h", uncommenting the hello world line, and including <iostream> in main (currently accessible through the template. Can anyone see what I'm missing here?
listtemplate.h
#ifndef LISTTEMPLATE_H
#define LISTTEMPLATE_H
#include "list.h"
using namespace std;
// Default constructor
template <class Type>
list<Type> :: list() : Head(NULL) {}
// Destructor
template <class Type>
list<Type> :: ~list()
{
Node *Temp;
while (Head != NULL)
{
Temp = Head;
Head = Head -> Next;
delete Temp;
}
}
// Copy constructor
template <class Type>
list<Type> :: list (const Type& OriginalList)
{
Node *Marker;
Node *OriginalMarker;
OriginalMarker = OriginalList.Gead;
if (OriginalMarker == NULL) Head = NULL;
else
{
Head = new Node (OriginalMarker -> Element, NULL);
Marker = Head;
OriginalMarker = OriginalMarker -> Next;
while (OriginalMarker != NULL)
{
Marker -> Next = new Node (OriginalMarker -> Next);
OriginalMarker = OriginalMarker -> Next;
Marker = Marker -> Next;
}
}
}
// Copy assignment operator
template <class Type>
list<Type>& list<Type> :: operator= (const list<Type>& Original)
{
Node *Marker;
Node *OriginalMarker;
// Check that we are not assigning a variable to itself
if (this != &Original)
{
// First clear the current list, if any
while (Head != NULL)
{
Marker = Head;
Head = Head -> Next;
delete Marker;
}
// Now build a new copy
OriginalMarker = Original.Head;
if (OriginalMarker == NULL) Head = NULL;
else
{
Head = new Node (OriginalMarker -> Element, NULL);
Marker = Head;
OriginalMarker = OriginalMarker -> Next;
while (OriginalMarker != NULL)
{
Marker -> Next = new Node (OriginalMarker -> Element, NULL);
OriginalMarker = OriginalMarker -> Next;
Marker = Marker -> Next;
}
}
}
return (*this);
}
// Test for emptiness
template <class Type>
bool list<Type> :: Empty() const
{
return (Head == NULL) ? true : false;
}
// Insert new element at beginning
template <class Type>
bool list<Type> :: Insert (const Type& NewElement)
{
Node *NewNode;
NewNode = new Node;
NewNode -> Element = NewElement;
NewNode -> Next = Head;
return true;
}
// Delete an element
template <class Type>
bool list<Type> :: Delete (const Type& DelElement)
{
Node *Temp;
Node *Previous;
// If list is empty
if (Empty()) return false;
// If element to delete is the first one
else if (Head -> Element == DelElement)
{
Temp = Head;
Head = Head -> Next;
delete Temp;
return true;
}
// If the list has only one element which isn't the specified element
else if (Head -> Next == NULL) return false;
// Else, search the list element by element to find the specified element
else
{
Previous = Head;
Temp = Head -> Next;
while ((Temp -> Element != DelElement) && (Temp -> NExt != NULL))
{
Previous = Temp;
Temp = Temp -> Next;
}
if (Temp -> Element == DelElement)
{
Previous -> Next = Temp -> Next;
delete Temp;
return true;
}
else return false;
}
}
// Print the contents of the list
template <class Type>
void list<Type> :: Print (ostream& OutStream) const
{
Node *Temp;
Temp = Head;
while (Temp != NULL)
{
OutStream << Temp -> Element << " ";
Temp = Temp -> Next;
}
}
// Overloaded output operator
template <class Type>
ostream& operator<< (ostream& OutStream, const list<Type>& OutList)
{
OutList.Print (OutStream);
return OutStream;
}
#endif
list.h
#ifndef LIST_H
#define LIST_H
#include <iostream>
#include <cstddef>
using namespace std;
template <class Type>
class list
{
private:
struct Node
{
public:
Type Element;
Node *Next;
Node() : Next(NULL) {} // Default constructor
Node (Type Data, Node *PNode = NULL) : // Non-default constructor
Element (Data),
Next (PNode) {}
};
Node *Head;
public:
list();
~list();
list (const Type& OriginalList);
bool Empty() const;
bool Insert (const Type& NewElement);
bool Delete (const Type& DelElement);
void Print (ostream& OutStream) const;
list& operator= (const list<Type>& Original);
};
template <class Type>
ostream& operator<< (ostream& OutStream, const Type& OutList);
#endif
This is in fact an interesting question. The main issue is, as others have pointed before that you have declared the following signature:
template <typename T>
std::ostream& operator<<( std::ostream&, T const & );
And that triggers the ambiguity, as it is a catch-all template. But why is it that the compiler can insert (unambiguously) an integer into cout but it cannot insert a const char*?
The reason for that is in the definition of the std::basic_ostream template and free functions that are required in the standard. In particular, the template class basic_ostream contains member functions to insert basic types, including int. On the other hand, the insertion of const char* into streams is defined as a templated free function. Bringing the three declarations together:
namespace std {
template <typename CharT, typename traits = char_traits<CharT> >
class basic_ostream {
// ...
basic_ostream<CharT,traits>& operator<<(int n); // [1]
// ...
};
template<class charT, class traits> // [2]
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const char*);
}
template <typename T> // [3]
std::ostream& operator<<( std::ostream&, T const & ); // user defined
Now, when the compiler encounters the expression std::cout << 5, it finds that [1] is a non-templated perfect match. It is non-templated as std::cout is an object of a concrete instantiation of the basic_ostream class template, when the compiler considers the members of that class, the type is fixed. The method itself is not templated.
The template [3] could match the same use, but because [1] is not templated it takes precedence in the overload resolution, and there is no ambiguity.
Now, when the compiler sees the expression std::cout << "Hello world";, it performs the lookup and it finds (among other options that cannot be matched and are thus discarded) options [2] and [3]. The problem is that now, both options are templates, the first one can be resolved by matching CharT = char and traits = char_traits<char>, while the second can be matched by making T = const char* (the first argument is a concrete instantiated type). The compiler cannot make up its mind (there is no partial order that defines which option it should follow), and it triggers the ambiguity error.
The really interesting point in the question is that while both [1] and [2] seem to be templated on the arguments CharT and traits basically in the same way they are not considered in the same way by the compiler, the reason for that is that lookup finds [1] as a member of std::cout, that means that in [1], basic_ostream<char,char_traits<char> > is the concrete known type of the first argument and it is fixed. The template is the class, not the function, and the class instantiation types are fixed before lookup considers the member functions. On the other hand, when it ADL finds [2] and tries to match against the call, basic_ostream<CharT, traits> is a generic type that can be matched to the type of cout.
I hope this is not too confusing, but I think it is nice to know the subtle difference of similarly looking code.
I think that the problem is that in your header you've prototyped this function:
template <class Type>
ostream& operator<< (ostream& OutStream, const Type& OutList);
instead of this one:
template <class Type>
ostream& operator<< (ostream& OutStream, const list<Type>& OutList);
The version you've prototyped says that it's an operator << that can print out anything, not lists of anything. Consequently, when you write
cout << "Hello, world!" << endl;
The compiler can't tell which function it's supposed to call - the standard output function or the one you've defined in your list header.
declared as:
ostream& operator<< (ostream& OutStream, const Type& OutList);
in the function definition as:
ostream& operator<< (ostream& OutStream, const list<Type>& OutList)