ToString for templated linked list? - c++

Here's my code:
template<typename T>
class list {
private:
node<T>* head;
node<T>* tail;
int len;
public:
list(){
this->len = 0;
this->head = this->tail = 0;
}
~list(){
node<T>* n = this->head;
if (!n) return;
node<T>* t = NULL;
while (n){
t = n->next;
delete n;
n = t;
}
}
/* other stuff */
ostream& operator<<(ostream &o, const list<T>& l) {
node<T>* t = l.head;
while (t){
strm << *(t->value);
if (!t->next) break;
strm << ", ";
t = t->next;
}
return strm;
}
};
I get the following compile error:
rm bin *.o -f
g++ -g -Wall main.cpp -o bin
main.cpp:110: error: 'std::ostream& list<T>::operator<<(std::ostream&, const list<T>&)' must take exactly one argumentmain.cpp: In function 'int main(int, char**)':
main.cpp:151: error: no match for 'operator<<' in 'std::cout << l'
/usr/include/c++/4.4/ostream:108: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
... other errors
make: *** [main] Error 1
So, here's my question. What do I need to do to make this work? I was trying to follow this question as an example.

Your operator<< is declared as a member function. You need to make it a free function instead, i.e. define it outside the class:
template <class T>
class list {
// ...
};
template <class T>
ostream& operator<<(ostream &o, const list<T>& l)
{
// ...
};
If you need to make your operator<< a friend of the class then please have a look at my answer to this question
Also, I noticed that you're using ostream without std::, implying that you're using using namespace std.
If you're doing that, then it's a really bad idea to call your class list, since there is a std::list that will be pulled into scope by using namespace std if #include <list> is added to the file at any time in the future.

Can you try to make the operator<< function as friend?
....;
friend ostream& operator<<(ostream &o, const list<T>& l) {
....;
This is because as shown in the other question, this function has to be declared as a free function, if declared as a member of list, it is only used if it is actually called on a list object itself.
Edit
Good catch by #je4d.
Looking at your code it looks like you dont need the operator to be a friend since im guessing you will have accessors for head and tail. It would be easier to just declare and define it outside the class as a templated free function.

I ended up using a combination of boost::lexical_cast<std::string> and the suggested ostream& operator << method.

Related

error overloading operator '>>'

I am trying to overload the >> operator, check my code, it's the most reduced program:
#include <iostream>
#include <string>
using namespace std;
class MyClass{
private:
string bar;
int foo;
public:
MyClass(){
bar="";
foo=0;
};
istream& operator>>(istream& is){
is >> bar >> foo;
return is;
};
ostream& operator<<(ostream& os){
os << bar << foo;
return os;
};
~MyClass(){};
};
int main()
{
MyClass* a = new MyClass();
cin >> *a;
delete a;
return 0;
}
This code doesn't compile, I've googled before post my question and I found the trouble could be the most vexing parse, but i cannot imagine how to fix it.
Anyway, I don't know where is the problem, when i try to compile, the compiler throws:
First:
error: no match for ‘operator>>’ (operand types are ‘std::istream {aka std::basic_istream<char>}’ and ‘MyClass’)
cin >> *a;
~~~~^~~~~
Then, after trying to convert the types to int, double, char, etc it throws:
/usr/include/c++/6.1.1/istream:924:5: nota: candidate:
std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&&, _Tp&) [con _CharT = char; _Traits = std::char_traits<char>; _Tp = MyClass] <coincidencia cercana>
operator>>(basic_istream<_CharT, _Traits>&& __is, _Tp& __x)
^~~~~~~~
/usr/include/c++/6.1.1/istream:924:5: nota: conversion of argument 1 would be ill-formed:
error: no se puede unir el l-valor ‘std::istream {aka std::basic_istream<char>}’ a ‘std::basic_istream<char>&&’
cin >> *a;
What can I do to solve this issue?
Overloading the input and output operators can't be done as member functions. The reason is that when you defined the >> or << operators as member functions the object instance of the class must be on the left hand side of the operator.
Instead define the operator functions as non-member friend functions (which can be done inline in the class) like
class MyClass
{
public:
...
friend std::ostream& operator<<(std::ostream& os, MyClass const& object)
{
return os << object.bar << object.foo;
}
};
">>" and "<<" operators are usually not implemented as member functions because the first argument is an implicit object of that class in a member function but you can do that and it will work if you would do something like *a >> cin in your main.Other wise implement these operators as global functions as explained in the above answer.

Error calling the overloaded istream operator in a Template Class

I want to overload the ">>" operator in a template class, but when I am trying to write someting into a vector I am getting some errors.
This is a part of my Vector function:
#include <iostream>
template<typename T>
class Vector
{
public:
T operator[](const int& i);
template <T> friend
std::ostream& operator<<(std::ostream& out, const Vector &v);
template <T> friend
std::istream& operator>>(std::istream& in, Vector<T> &v);
};
template<typename T>
std::istream& operator>>(std::istream& in, Vector<T> &v) {
for(int i =0; i < v.getSize(); i++) {
in >> v[i];
}
}
I used this test to write into a vector:
int main {
Vector<int> v1(5);
cin >> v1;
}
This is the error:
Vector.h: In function ‘std::istream& operator>>(std::istream&, Vector<T>&) [with T = int, std::istream = std::basic_istream<char>]’:
testVector.cpp:9:9: instantiated from here
Vector.h:94:3: error: ambiguous overload for ‘operator>>’ in ‘in >> (& v)->Vector<T>::operator[] [with T = int]((*(const int*)(& i)))’
Vector.h:94:3: note: candidates are:
/usr/include/c++/4.6/istream:122:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__istream_type& (*)(std::basic_istream<_CharT, _Traits>::__istream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT,
This is a part of my code. If I am using in a test function only something like this, it compiles:
Vector<int> v1.
cout << v1.getSize();
Update:
I've modified the >> operator overloading definition like this:
template<typename T> std::istream& operator>>(std::istream& in, Vector<T> &v) {
T tmp;
for(int i =0; i < v.getSize(); i++) {
in >> tmp;
v[i] = tmp;
}
}
This is the definition of the operator[]:
template<typename T> T Vector<T>::operator[](const int& i) {
return elements[i];
}
I get this error:
Vector.h:96:3: error: lvalue required as left operand of assignment
How should I overwrite the >> operator?
Thanks.
These lines:
template <T> friend std::ostream& ...
template <T> friend std::istream& ...
The template argument should be a type. As you've written it, it takes an object of said type.
template<typename U> friend std::ostream& ...
template<typename U> friend std::istream& ...
And you didn't specify a template argument here:
Vector v1(5);
^
Your problem has nothing to do with stream overloading:
You have two constructors with the same argument int. The names of the constructor doesn't matter main thing is the type. So two Vector<T>(int) will give you error overloading error.
You do not have an overloaded subscript operator (operator[]), set it up to fix the main problem
as 0x499602D2 mentioned, change the friend classes to the correct form because you will get error "accessing private member variable of class Vector" if you tried to use private members. In your scenario, you are accessing public members, so you might not even need friending the stream overloading. Read about friend here. So, ask yourself a question? "Will the stream operator function access the private member of class Vector?" If yes, use friend; otherwise remove it from your class declaration.
Remove the def from the source code. We understand that its coming from a source file.
The test program doesn't work because you haven't specified which template parameter you are using.
EDIT: added link for (3) to read about friendship

Conversion operators

This code is not compilable.
I can't find why in standard. Can someone explain?
#include <iostream>
#include <string>
template<typename T>
class S
{
public:
explicit S(const std::string& s_):s(s_)
{
}
std::ostream& print(std::ostream& os) const
{
os << s << std::endl;
return os;
}
private:
std::string s;
};
template<typename T>
std::ostream& operator << (std::ostream& os, const S<T>& obj)
{
return obj.print(os);
}
/*template<>
std::ostream& operator << <std::string> (std::ostream& os, const S<std::string>& obj)
{
return obj.print(os);
}*/
class Test
{
public:
explicit Test(const std::string& s_):s(s_)
{
}
//operator std::string() const { return s; }
operator S<std::string>() const { return S<std::string>(s); }
private:
std::string s;
};
int main()
{
Test t("Hello");
std::cout << t << std::endl;
}
Compiler output:
source.cpp: In function 'int main()':
source.cpp:47:17: error: no match for 'operator<<' in 'std::cout << t'
source.cpp:47:17: note: candidates are:
In file included from include/c++/4.7.1/iostream:40:0,
from source.cpp:1:
include/c++/4.7.1/ostream:106:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
include/c++/4.7.1/ostream:106:7: note: no known conversion for argument 1 from 'Test' to 'std::basic_ostream<char>::__ostream_type& (*)(std::basic_ostream<char>::__ostream_type&) {aka std::basic_ostream<char>& (*)(std::basic_ostream<char>&)}'
....
Thats because no conversions, except for array-to-pointer, function-to-pointer, lvalue-to-rvalue and top-level const/volatile removal (cf. c++11 or c++03, 14.8.2.1), are considered when matching a template function. Specifically, your user-defined conversion operator Test -> S<string> is not considered when deducing T for your operator<< overload, and that fails.
To make this universal overload work, you must do all the work at the receiving side:
template <class T>
typename enable_if<is_S<T>::value, ostream&>::type operator <<(ostream&, const T&);
That overload would take any T, if it weren't for the enable_if (it would be unfortunate, since we don't want it to interfere with other operator<< overloads). is_S would be a traits type that would tell you that T is in fact S<...>.
Plus, there's no way the compiler can guess (or at least it doesn't try) that you intended to convert Test to a S<string> and not S<void> or whatever (this conversion could be enabled by eg. a converting constructor in S). So you have to specify that
Test is (convertible to) an S too
the template parameter of S, when converting a Test, is string
template <class T>
struct is_S {
static const bool value = false;
};
template <class T>
struct is_S<S<T>> {
static const bool value = true;
typedef T T_type;
};
template <>
struct is_S<Test> {
static const bool value = true;
typedef string T_type;
};
You will have to convert the T to the correct S manually in the operator<< overload (eg. S<typename is_S<T>::T_type> s = t, or, if you want to avoid unnecessary copying, const S<typename is_S<T>::T_type> &s = t).
The first paragraph of #jpalecek's answer explains what the issue is. If you need a workaround, you could add a declaration like:
inline std::ostream& operator<< (std::ostream& os, const S<std::string>& s)
{ return operator<< <> (os, s); }
Since that overload is not a template, implicit conversions to S<std::string> will be considered.
But I can't see any way to do this for all types S<T>...

The instantiation of the template class is wrong

The g++ compiler prompt the following statement is wrong:
template<typename Type>
class SingleList{
public:
SingleList()
{
head = new SingleListNode<Type> () ; //Error happens here!!!
}
The error message is :
./inc/single_list.h: In instantiation of ‘SingleListNode<int>’:
./inc/single_list.h|39 col 13| instantiated from ‘SingleList<Type>::SingleList() [with Type = int]’
The definition of head is the following, maybe problem is not related here.
SingleListNode<Type> *head;
The instantiation of class SingleList in main function is :
int main()
{
SingleList<int> list;
I don't know where the syntax error happens, can anyone help me? Thanks!!
========================================================================
The following is the content of source file:
template<typename Type> class SingleList;
template<typename Type> class SingleListNode{
private:
friend class SingleList<Type>;
SingleListNode() : next(NULL){}
public:
friend ostream& operator<< <Type>(ostream& os,SingleListNode<Type>& sln); //Error here!!
private:
SingleListNode *next;
};
template<typename Type> ostream& operator<<(ostream& os,SingleListNode<Type>& out){
os<<out.data;
return os;
}
template<typename Type> class SingleList{
public:
SingleList()
{
head = new SingleListNode<Type> () ; //Error happens here.
}
~SingleList(){
delete head; //Same error
}
private:
SingleListNode<Type> *head;
};
The error message prompted by g++
|| g++ -g -I ./inc/ -c single_list_test.cpp -o single_list_test.o
|| single_list.h: In instantiation of ‘SingleListNode<int>’:
single_list.h|25 col 13| instantiated from ‘SingleList<Type>::SingleList() [with Type = int]’
single_list_test.cpp|9 col 18| instantiated from here
single_list.h|10 col 18| error: template-id ‘operator<< <int>’ for ‘std::ostream& operator<<(std::ostream&, SingleListNode<int>&)’ does not match any template declaration
|| make: *** [single_list_test.o] Error 1
To my gcc , just modify the following statement
friend ostream& operator<< <Type>(ostream& os,SingleListNode<Type>& sln)
to
friend ostream& operator<< (ostream& os,SingleListNode<Type>& sln)

Some compiler errors concerning an overloaded operator on a template in c++

I have some code with a few errorr I do not understand how to fix at all. I have asked my professor and TA, and consulted the internet with no luck, apart from understanding more precisely what the errors mean. From what I can tell, the compiler is either confusing my overloaded operator with built in operators, or it is not recognizing it as an overloaded operator at all.
I am getting the following errors and warnings:
||=== project 4, Debug ===|
\project 4\forest.h|13|warning: friend declaration 'Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&)' declares a non-template function|
\project 4\forest.h|13|note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) |
\project 4\forest.h|14|warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Forest<NODETYPE>&)' declares a non-template function|
\project 4\forest.h|15|warning: friend declaration 'std::istream& operator>>(std::istream&, Forest<NODETYPE>&)' declares a non-template function|
\project 4\main.cpp||In function 'int main()':|
\project 4\main.cpp|21|error: ambiguous overload for 'operator>>' in 'file >> intForest'|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|119|note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|123|note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|130|note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|
||=== Build finished: 1 errors, 3 warnings ===|
When I try to compile my code. The relevant code segments are as follows:
(in forest.h)
template< typename NODETYPE > class Forest
{
public:
friend Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&);
friend ostream& operator<<(ostream&, const Forest<NODETYPE>&);
friend istream& operator>>(istream&, Forest<NODETYPE>&);
Forest();
Forest( const Forest& otherForest);
~Forest();
void nodes(int&) const;
private:
ForestNode<NODETYPE> *root;
ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};
(in forest.cpp)
template<typename NODETYPE> istream& operator>>(istream& file, const Forest<NODETYPE>& f1)
{
istream file2 = file;
int nodeCount = 0;
string blah = ' ';
while(getline(file2,blah))
{
nodeCount++;
}
ForestNode<NODETYPE> *forestNodeArray[nodeCount];//holds pointers to last node of depth i
getline(file,*f1.root.tag);
forestNodeArray[0] = &(*f1.root);
inputHelper(file, 0, *f1.root, forestNodeArray, nodeCount);
return file;
}
(and finally, in main.cpp)
int main()
{
Forest < char > intForest();
filebuf fb;
fb.open ("forest1.txt",ios::in);
istream file(&fb);
cout << typeid(intForest).name() << endl;
cout << typeid(file).name() << endl;
file >> intForest;
fb.close();
}
Any help would be greatly appreciated.
EDIT: Thanks to alex and alf, I understand why they were not considered template functions. It's quite obvious in retrospect, I was just set on those signatures. Anyway, I still get the error about the ambiguous operator. Why does the compiler not recognize my operator and use it, instead of trying to decide between 3 built in versions of the operator that could not possibly have one parameter as Forest?
The second error is in this line:
Forest < char > intForest();
This may be surprising at first, but that line is not declaring a variable of type Forest<char>, but rather a function that takes no arguments and returns a Forest<char>.
Just remove the parenthesis from the declaration:
Forest < char > intForest;
On the first warning, which is already explained (the function declared as friend is not a template, and that means that you will manually have to implement it for each type you use to instantiate Forest<> with (probably you don't want that). Also note that declaring the templated operator+ and then making the template a friend as in #Alf P. Steinbach answer means that a Forest<int> will be a friend of a Forest<double>, which might not be what you need. #Alex proposal in the comment will only make a particular instantiation of the template a friend, which is probably closer to what you want, but you need to declare the templated operator before the template class, and for that you will need to forward declare the template class...
A common pattern for friend free functions in templates is defining the function in place:
template <typename T>
class Forest {
// ...
friend Forest& operator+( Forest const & lhs, Forest const & rhs ) [1]
{
// implementation here
}
}
// [1] Note that the arguments are const references (read only), and also note that
// you do not need to provide the type argument inside the template declaration
This allows you to define it as a non templated function and at the same time have the compiler instantiate the function for you. Also, it is usually simpler to also define member methods inlined in the class definition when dealing with templates. It makes life simpler, and after all in most cases you do need to provide the implementation in the (same) header file.
Yet, when defining binary operators a better approach is to define operator+= as a member method, and then you can easily define operator+ as a non-friend free function. The pattern would be:
struct test {
test& operator+=( test const & );
};
test operator+( test lhs, test const & rhs ) { // [2]
lhs += rhs;
return lhs;
}
// [2] Note that the first argument is by value, and the second by const reference
// This means that the compiler will copy the first argument for you, and you
// are free to modify it with the += operator and return the copy.
Now, the most tricky part is mixing the previous two advices. To be able to define operator+ that is a free function inside the template definition, a common trick is to make it friend even if that is not required for access reasons:
template <typename T>
class Forest {
Forest& operator+=( Forest const & ) {
// implemenation
}
friend Forest operator+( Forest lhs, Forest const & rhs ) { // [3]
return lhs+=rhs;
}
};
// [3] friendship only to allow us to define the free function inside the template
// declaration.
The (first) warning tells you that the befriended function is not a template.
And it isn't.
Think about how you would implement it. It would entail writing one such function for each possible NODE_TYPE.
There are several ways to fix that.
One way is to befriend a function template, like so:
template< class Type >
struct S
{
template< class U > friend void foo( S<U> );
};
template< class Type >
void foo( S< Type > x ) {}
int main()
{}
Cheers & hth.,
learning C++,I also encountered the same problem.But I had solved it for another way!
template <class NODETYPE> class Forest;
template <class NODETYPE> Forest<NODETYPE>& operator+ (Forest<NODETYPE>&, Forest<NODETYPE>&);
template <class NODETYPE> ostream& operator<<(ostream&, const Forest<NODETYPE>&);
template <class NODETYPE> istream& operator>> (istream&, Forest<NODETYPE>&);
template<class NODETYPE>
template< typename NODETYPE >
class Forest
{
public:
friend Forest<NODETYPE>& operator+ <>(Forest<NODETYPE>&, Forest<NODETYPE>&);
friend ostream& operator<< <>(ostream&, const Forest<NODETYPE>&);
friend istream& operator>> <>(istream&, Forest<NODETYPE>&);
Forest();
Forest( const Forest& otherForest);
~Forest();
void nodes(int&) const;
private:
ForestNode<NODETYPE> *root;
ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};